How to query parameters correctly in JS? - javascript

I'm trying to query parameters localhost:8888?title=associate&name=John and I have written the code below, but editor shows errors in if-else statement. Is the whole concept incorrect? The idea is that if there's no parameters, it would use the default values "who" and "department".
const handleRequest = (request) => {
const url = new URL(request.url);
const params = url.searchParams;
let who = "employee";
let department = "admin";
if (params.has("title") || params.has("name")) {
return new Response(`Please address your request to ${params.get("title")} called ${params.get("name")}.`);
} else {
return new Response(`Please address your request to ${who} in the ${department}.`);
}
};

URLSearchParams object provides lots of methods (like get(param), has(param)) to access the query string parameters.
const url = new URL(
'http://example.com/path/index.html?message=hello&who=world'
);
url.searchParams.get('message'); // => 'hello'
url.searchParams.get('missing'); // => null
//So you can simply use
let messageParam = url.searchParams.get("message") || "default value";
You can read more about it here
https://dmitripavlutin.com/parse-url-javascript/#31-parsing-query-string

Related

JS: Cannot search for two parameters - async gives back only the first parameter

I am trying for a day now and cannot solve this problem:
I have a website where I can add contacts to a SQLite database. I want to query the database by studentID or nachname (this means last name). I have an API endpoint which seems to be working and a getContact function which only works for the first parameter. In this case it only searches for studentID and if I change the order I can only get my data by nachname.
For now I just want to display the response simply at the URL localhost:8000/api/contacts/studentID or /nachname to see the json response.
I tried this getContact function:
async getContact(**studentID, nachname**) { //here only the first parameter works
let result = [];
let query;
let params = [];
if (studentID && !nachname) {
query = "SELECT * FROM contacts WHERE studentID = ?";
params.push(studentID);
} else if (nachname && !studentID) {
query = "SELECT * FROM contacts WHERE nachname = ?";
params.push(nachname);
} else if (studentID && nachname) {
query = "SELECT * FROM contacts WHERE studentID = ? OR nachname = ?";
params.push(studentID, nachname);
}
result = await new Promise((resolve, reject) => {
db.all(query, params, (error, row) => {
if (error) {
reject(error);
} else {
resolve(row);
}
});
});
return result;
}
My API endpoint (setup with Express.js in Node.js) looks like this currently:
app
.get("/api/contacts/:studentID?/:nachname?", async (request, response) => {
const studentID = request.params.studentID;
const nachname = request.params.nachname;
console.log(request.params.studentID);
console.log(request.params.nachname);
const contact = await contactsManager.getContact(studentID, nachname);
if (contact) {
response.status(200).send(contact);
} else {
response.status(404);
}
})
I don't understand why the getContact function only works with the first parameter.
One strange thing I recognized: Right now I could search for localhost:8000/api/contacts/1 and would see the right entry, and when I add .../contacts/1/Behrens I see the entry with the ID 1 and also the entries of the people named Behrens. Maybe this information helps?
The issue is that in your getContact function, you are using the ** operator in front of studentID and nachname, which is causing them to be treated as keyword arguments instead of regular arguments. As a result, the function is only able to identify and use the first argument passed to it, while the second argument is ignored.
To fix this, you should remove the ** operator from the function definition so that the function takes in two regular arguments:
async getContact(studentID, nachname) {
// ...
}
Also, you can use SELECT * FROM contacts WHERE studentID = ? AND nachname = ? instead of SELECT * FROM contacts WHERE studentID = ? OR nachname = ? if you want to check the both parameter are exist in the database.
Also, you should check for the existence of the parameters in the API endpoint before passing them to the getContact function, otherwise, you may end up passing undefined values to the function which will cause an error.
app.get("/api/contacts/:studentID?/:nachname?", async (request, response) => {
let studentID = request.params.studentID;
let nachname = request.params.nachname;
if(!studentID) studentID = null;
if(!nachname) nachname = null;
console.log(studentID);
console.log(nachname);
const contact = await contactsManager.getContact(studentID, nachname);
if (contact) {
response.status(200).send(contact);
} else {
response.status(404);
}
})
Also, you can use only one parameter in the endpoint and use if-else statements to check which parameter is passed and then act accordingly in the function.
app.get("/api/contacts/:param?", async (request, response) => {
let studentID = request.params.param;
let nachname = request.params.param;
if(studentID.match(/^\d+$/)){
studentID = request.params.param;
nachname = null;
}else{
studentID = null;
nachname = request.params.param;
}
console.log(studentID);
console.log(nachname);
const contact = await contactsManager.getContact(studentID, nachname);
if (contact) {
response.status(200).send(contact);
} else {
response.status(404);
}
})
This should fix the issue with the getContact function only working with the first parameter, and allow you to query the database by both studentID and nachname.

Alter a object variable inside cloud functions

I am trying to alter a object variable after query in cloud functions, but before sending it to my app, but not sure how to do so! Here is what I am trying to do:
Parse.Cloud.define("getUserData", async(request) => {
// Getting the users data
const userQuery = new Parse.Query("UserData");
userQuery.equalTo("userId", request.params.userId);
const userData = await userQuery.first();
// Getting the groups
const groupQuery = new Parse.Query("GroupMembers");
groupQuery.equalTo("userId", request.params.userId);
groupQuery.include('pointerObject'); // including the pointer object
const groups = await groupQuery.find();
const allGroups = [];
for (let i = 0; i < groups.length; ++i) {
var thisGroup = groups[i].get("pointerObject");
thisGroup.isFavorite = true;
allGroups.push(thisGroup);
}
var returnObject = {
"playerData": userData,
"playerGroups": allGroups
}
const jsonString = JSON.stringify(returnObject);
return jsonString;
});
It is "thisGroup.isFavorite" i am trying to set to true, but when receiving the jsonString, it is still set to false? How do I alter a variable in cloud functions?
Any help is appreciated and thanks in advance :-)
Try with:
thisGroup.set('isFavorite', true);
await thisGroup.save();

Swapping out Constants for a Function

I'm trying to refactor the following code, which depending on the top level domain of the recipients email, changes where you click through to in my button. I currently do this with two consts, which I need to refactor into only one.
const CCENTERURL_AT= `${HOSTURL_AT}/ccenter/zendesk/landing/`;
const CCENTERURL = `${HOSTURL}.com/ccenter/zendesk/landing/`;
const recipientEmail = data.ticket.recipient;
var cCenterUrl;
if(recipientEmail.indexOf(".com") > 0)
{
cCenterUrl = getCcenterUrl(zendeskID)
}else{
cCenterUrl = getAustrianCcenterUrl(zendeskID)
}
function getCcenterUrl(ticketID) {
const cCenterTicketUrl = CCENTERURL + ticketID ;
return cCenterTicketUrl;
}
// Get Austrian Ccenter Ticket Url using Zendesk ticket ID
function getAustrianCcenterUrl(ticketID) {
const cCenterTicketUrlAustria = CCENTERURL_AT + ticketID ;
return cCenterTicketUrlAustria;
}
I know I should be able to create a function which will take recipient Email`s top-level domain as parameter and return appropriate URL for CCENTERURL. But no matter what I've tried its become overcomplicated or hasn't worked. I would be interested to hear peoples opinions on either how I can achieve my goal or even how it would be better to go about this!
So you basically want to combine these into one function and use a string template like this.
const HOSTURL = 'example.com/'
const HOSTURL_AT = 'example.au/'
const reAu = /\.au$/;
const getTicketURL = (
(mail, id) => `${ reAu.test(mail) > 0 ? HOSTURL : HOSTURL_AT }ccenter/zendesk/landing/${id}`
);
// Test AU
console.log(getTicketURL('foo#google.com.au', 'ABC1231'))
// Test US
console.log(getTicketURL('foo#google.com', 'ABC1231'))

JS constructor can not see the variable

I'm trying to use Twilio Access Token on Firebase Functions with TypeScript.
export const returnToken = functions.https.onRequest((req, res) => {
const twilioAccessToken = twilio.jwt.AccessToken;
const envconf = functions.config();
const twilioAccountSid = envconf.twilio.sid; //saved them on environment
console.log(twilioAccountSid); //prints out fine
console.log(typeof twilioAccountSid !== "undefined"); //returns true
const twilioApiKey = envconf.twilio.apikey;
console.log(twilioApiKey); //prints fine too
const twilioApiSecret = envconf.twilio.apisecret;
console.log("gonna make a token"); //prints
const token = twilioAccessToken( //here it says TypeError: Cannot set property 'accountSid' of undefined
twilioAccountSid,
twilioApiKey,
twilioApiSecret
)
console.log("gonna make a grant");
const grant = new twilioAccessToken.VideoGrant();
token.addGrant(grant);
grant.room = "someroom";
token.identity = "someid";
res.send(token.toJwt());
})
and I get an error for the twilioAccessToken constructor which says
TypeError: Cannot set property 'accountSid' of undefined
Looking the source ->
function AccessToken(accountSid, keySid, secret, options) {
if (!accountSid) { throw new Error('accountSid is required'); }
if (!keySid) { throw new Error('keySid is required'); }
if (!secret) { throw new Error('secret is required'); }
options = options || {};
this.accountSid = accountSid;
AccessToken is a constructor, but your calling it like a regular function..
const token = twilioAccessToken(
You need to use new
const token = new twilioAccessToken(
Normal Javascript notation is if a function starts with a capital letter, it's a hint that it's a constructor. To keep with this standard I would say you want to also rename twilioAccessToken to TwilioAccessToken..

Value of map from DynamoDB is undefined in Node.js

I have a Lambda function which runs in Node.js 4.3. The input parameter of the function is a String, which is being sent from an AWS Lex bot.
I want to get an item from a DynamoDB table. In this item I have a Map-type attribute, which contains a String key and String value. I want to get a value from that map using the key String I got as a parameter at the start of the function.
The problem is that when I log the map to the console, all I see there is {}.
This is my code:
var AWS = require('aws-sdk');
AWS.config.region = 'us-east-1';
var dynamodb = new AWS.DynamoDB();
const sessionAttributes = intentRequest.sessionAttributes;
const slots = intentRequest.currentIntent.slots;
const name = slots.names;
var id = null;
if (name == "a") {
id = "00";
} else if (name == "b") {
id = "01";
}
var params = {
TableName: 'names',
Key: {
'id' : {S: 'test-id'}
}
};
var names = {};
dynamodb.getItem(params, function(err, data) {
if (err) {
console.log(err); // an error occurred
} else {
names = data.Item.names.M;
}
});
console.log(names);
var content = names[id];
callback(close(sessionAttributes, 'Fulfilled',
{'contentType': 'PlainText', 'content': content}));
As you can see, there is a console.log line at the end of the code. This line logs just {}. The final message's content is undefined.
What can I do to fix this?
dynamodb.getItem() is executing asynchronously, it has a callback function for this very reason.
console.log(names) is executing before any value is returned in the call to dynamodb.
Add a console.log() inside the getItem function and you will see that this is true.
Google "asynchronous javascript" and you'll find some good pointers.

Categories

Resources