Why am i getting undefined when trying to get a single element? - json

Why am i getting undefined of my id? I am creating an app with NextJS and i am trying to do a route to get an especific element by its id. This is my route:
const { events } = require('../../../db.json')
const handler = async (req , res) => {
const method = req.method;
const evt = events.filter((ev) => ev.id === req.query.params.id);
if(method === 'GET'){
return res.status(201).json(evt);
} else {
res.setHeader('Allow', ['GET']);
res.status(405).json({message:`Method ${method} is not allowed`})
}
}
For some reason i get this error when i go to http://localhost:3000/api/events/1
I am using json web server so i have my api also running in port 3001 so at http://localhost:3001/api/events/1 it works and show the corresponding id but why is not working in port 3000 also?

Try updating your code to the following:
const { events } = require('../../../db.json');
const handler = async (req, res) => {
const method = req.method;
const id = req.query.id;
const evt = events.filter((ev) => ev.id === id);
if (method === 'GET') {
return res.status(201).json(evt);
} else {
res.setHeader('Allow', ['GET']);
res.status(405).json({ message: `Method ${method} is not allowed` });
}
};

Related

How to pass updated set State value in axios request as params

I'm a beginner in react native, I'm trying to get user information from mysql database through an axios API get request.
Once logged in, I stored email address in AsyncStorage and later want to use that email address from AsyncStorage as params or parameters to get the user details.
I wrote a code which set initial state of the setState as 'na'. Please help me how I can pass the email address from AsyncStorage as params or parameters.
Here is my code.
// to load email address
const [SessionEmail, setSessionEmail] = useState('na');
// to load users info
const [users, setUsers] = useState([]);
useFocusEffect(
React.useCallback(() => {
getUsername();
getUsersInfoFromAPI();
}, [])
);
// to get the session username from localstorage
const getUsername = async () => {
try {
const username = await AsyncStorage.getItem('Username')
if (username !== null) {
setSessionEmail(username);
}
} catch (e) {
console.log(e);
}
}
// API Calling user details
const getUsersInfoFromAPI = async () => {
await axios.get(`https://myapi.co.in/api/user/?email=${SessionEmail}`)
.then(response => {
setUser(response.data);
})
.catch(error => {
console.log(error);
});
}
After the page is rendered, and I load page from metro, I can see the parameters have been sent to server.
Update your code in this way:
useFocusEffect(
React.useCallback(() => {
getUsername();
}, [])
);
Instead of saving your email to state, sent it to function directly but if you are using it for other reason you can still save it but call function while getting username from AsyncStorage with username parameter like below.
// to get the session username from localstorage
const getUsername = async () => {
try {
const username = await AsyncStorage.getItem('Username')
if (username !== null) {
getUsersInfoFromAPI(username);
}
} catch (e) {
console.log(e);
}
}
// API Calling user details
const getUsersInfoFromAPI = async (email) => {
await axios.get(`https://myapi.co.in/api/user/?email=${email}`)
.then(response => {
setUser(response.data);
})
.catch(error => {
console.log(error);
});
}
const [users, setUsers] = useState([]);
here you can use like this
const [users, setUsers] = useState();
hope this will help you

How do I return an asynchronous DB query result from one module to another using Node.js?

I'm new to Node, and I'm trying to follow a pattern from a Udemy API course. The API is structured to utilize route, controller and service modules for flow. Database queries are to be run as services and they are supposed to be called from controllers.
I need to run a series of DB queries to generate a list (I'm showing only 2 of 6 queries in this example). I am running these using async/await in my function. The queries are working fine. My problem occurs when I try to return the 'batch result' (the result of all the queries) to the controller at the end of the process. I get Promise { <pending> }. I have tried many things, but I cannot end the promise to access the final result from my controller module--I can only access it from my service module.
Here is my code from my controller module (groups.controller.js) where I call my function:
const groupsService = require('../services/groups.service');
exports.propertyList = (req, res, next) => {
const uid = req.body.uid;
const batchResponse = groupsService.batchQuery(uid, res);
console.log(batchResponse);
}
And here is my code from my service module (groups.services.js) where I run the queries:
const mysql = require('mysql2');
const dbAsync = require("../config/db.config");
async function batchQuery(uid, res) {
var Q1;
var Q2;
var uid = uid * -1;
const pool = mysql.createPool(dbAsync.dbAsync);
const promisePool = pool.promise();
try {
Q1 = await promisePool.query('SELECT PropertyID FROM GroupMembership WHERE GroupID = ?', [uid]);
Q2 = await promisePool.query('SELECT SubGroupID FROM GroupMembership WHERE GroupID = ? AND PropertyID = ?', [uid, 0]);
}
catch(error) {
console.log(error);
res.status(401).send('Server error');
return error;
}
finally {
const batchResponse = {
Q1: Q1[0],
Q2: Q2[0]
}
console.log('Q1: '+ Q1[0][0].PropertyID + ', Q2: ' + Q2[0][0].SubGroupID);
res.status(200).send(batchResponse);
return batchResponse;
}
}
module.exports = {batchQuery};
When I send a post via postman, I get the expected query result (below). However, I can only get this to work if I put my res in my service module.
{
"Q1": [
{
"PropertyID": 0
}
],
"Q2": [
{
"SubGroupID": 397
}
]
}
Is there a way to end the promise in this pattern and return the desired batch response? Thank you.
EDIT: Adding the code updates provided by #traynor.
New controller:
const groupsService = require('../services/groups.service');
exports.propertyList = async (req, res, next) => {
const uid = req.body.uid;
let batchResponse;
try {
batchResponse = await groupsService.batchQuery(uid);
console.log(batchResponse);
return res.status(200).send(batchResponse);
} catch(error) {
console.log('Error: ' + error);
return res.status(401).send('Server error');
}
}
New service:
const mysql = require('mysql2');
const dbAsync = require("../config/db.config");
function batchQuery(uid) {
return new Promise((resolve, reject) => {
var Q1;
var Q2;
var uid = uid * -1;
const pool = mysql.createPool(dbAsync.dbAsync);
const promisePool = pool.promise();
try {
Q1 = await promisePool.query('SELECT PropertyID FROM GroupMembership WHERE GroupID = ?', [uid]);
Q2 = await promisePool.query('SELECT SubGroupID FROM GroupMembership WHERE GroupID = ? AND PropertyID = ?', [uid, 0]);
} catch(error) {
console.log(error);
reject(error);
} finally {
const batchResponse = {
Q1: Q1[0],
Q2: Q2[0]
}
console.log('Q1: '+ Q1[0][0].PropertyID + ', Q2: ' + Q2[0][0].SubGroupID);
resolve(batchResponse);
}
})
}
module.exports = {batchQuery};
the service is now returning a promise, and it's also handling response instead of controller.
to return from service, you need to promisify service: return a promise which resolves when you get db data, or on error, and then you also need to await the service, which it's wrapped in try/catch for error handling.
once it's all done, handle response from the controller:
service:
function batchQuery(uid) {
return new Promise(async (resolve, reject) => {
var Q1;
var Q2;
//...
try {
//...
} catch (error) {
console.log(error);
reject(error);
} finally {
const batchResponse = {
Q1: Q1[0],
Q2: Q2[0]
}
console.log('Q1: ' + Q1[0][0].PropertyID + ', Q2: ' + Q2[0][0].SubGroupID);
resolve(batchResponse);
}
});
controller:
exports.propertyList = async (req, res, next) => {
const uid = req.body.uid;
let batchResponse;
try {
batchResponse = await groupsService.batchQuery(uid);
console.log(batchResponse);
res.status(200).send(batchResponse);
} catch(error) {
return res.status(401).send('Server error');
}
}

Wikipedia API not working alexa javascript

i am very new to amazon skill and javascript and i am trying to create a skill that returns wikipedia first paragraph. I am trying to use Promise to retrieve content from external api however I can't seem to find my issue. I have tried async and await as well but didn't get anywhere with it.
This is my code
'''
const GetInfoIntentHandler = {
canHandle(handlerInput) {
return (
handlerInput.requestEnvelope.request.type === "IntentRequest" &&
handlerInput.requestEnvelope.request.intent.name === "GetInfoIntent"
);
},
async handle(handlerInput) {
let outputSpeech = 'This is the default message.';
await getRemoteData("https://en.wikipedia.org/w/api.php?action=query&list=search&srsearch=god&origin=*&format=json")
.then((response) => {
const data = JSON.parse(response);
outputSpeech = data;
})
.catch((err) => {
console.log(`ERROR: ${err.message}`);
// set an optional error message here
outputSpeech = "hereeeee";
});
return handlerInput.responseBuilder
.speak(outputSpeech)
.getResponse();
},
};
const getRemoteData = (url) => new Promise((resolve, reject) => {
const client = url.startsWith('https') ? require('https') : require('http');
const request = client.get(url, (response) => {
if (response.statusCode < 200 || response.statusCode > 299) {
reject(new Error(`Failed with status code: ${response.statusCode}`));
}
const body = [];
response.on('data', (chunk) => body.push(chunk));
});
//request.on('error', (err) => reject(err));
});
'''
[My error][1]
This is the API i am using:"https://en.wikipedia.org/w/api.php?format=json&origin=*&action=query&prop=extracts&exlimit=max&explaintext&titles="+query+"&redirects=",
[My BUILD ][2]
Can you please tell me where i am going wrong
[1]: https://i.stack.imgur.com/Gvp2Q.png
[2]: https://i.stack.imgur.com/bAvzR.png

cloud function for sending fcm notifications to a collection of tokens

I am trying to send a notification whenever a new update to my database takes place. I have the onUpdate side working but I am new to FCM and I am stuck at the sending the notification.
The structure of the devices collection is:
+devices/
+tokenId/
-tokenId:njurhvnlkdnvlksnvlñaksnvlkak
-userId:nkjnjfnwjfnwlknlkdwqkwdkqwdd
The function that I have right now that gets stuck with an empty value of token is:
const functions = require('firebase-functions');
const admin = require("firebase-admin");
admin.initializeApp();
const db = admin.firestore();
const settings = { timestampsInSnapshots: true };
db.settings(settings);
.....
exports.fcmSend = functions.firestore
.document(`chats/{chatId}`).onUpdate((change, context) => {
const messageArray = change.after.data().messages;
const message = messageArray[(messageArray.length-1)].content
if (!change.after.data()) {
return console.log('nothing new');
}
const payload = {
notification: {
title: "nuevo co-lab",
body: message,
}
};
return admin.database().ref(`/devices`)
.once('value')
.then(token => token.val())
.then(userFcmToken => {
console.log("Sending...", userFcmToken);
return admin.messaging().sendToDevice(userFcmToken, payload)
})
.then(res => {
console.log("Sent Successfully", res);
})
.catch(err => {
console.log("Error: ", err);
});
});
I am not able to get the token from the database. It is null or undefined. Can anyone help me with this second part of the function?
Thanks a lot in advance!
Thanks Frank for the tip!
I managed to solve the problem with this code in case anybody needs it:
const payload = {
notification: {
title: "nuevo mensaje de co-lab",
body: message,
}
};
// Get the list of device tokens.
const allTokens = await admin.firestore().collection('devices').get();
const tokens = [];
allTokens.forEach((tokenDoc) => {
tokens.push(tokenDoc.id);
});
if (tokens.length > 0) {
// Send notifications to all tokens.
return await admin.messaging().sendToDevice(tokens, payload);
}else {
return null;
}

Reading a JSON file in NodeJs

I have a small JSON file with this content
{
"users": [
{
"id": 1593,
"name": "Foo Bar"
}
]
}
and I want to read this content by using the filesystem module. So my application looks this
const fs = require('fs');
const express = require('express');
const app = express();
app.get('/users/:id', function (req, res) {
fs.readFile('./userDb.json', 'utf8', function (err, data) {
var json = JSON.parse(data);
var users = json.users;
console.log(users[0].id); // returns 1593
console.log(req.params.id); // returns 1593
var userObj = null;
for(var i = 0; i < users.length; i++){
var currentUser = users[i];
console.log(currentUser.id); // returns 1593
if (currentUser.id === req.params.id) { // this should be fine 1593 === 1593
userObj = currentUser;
break;
}
}
console.log(userObj); // returns undefined
res.render('users', {
user: userObj
});
});
});
app.listen(3000, function () {
console.log('Server running on port 3000');
});
The log will always return 1593, when I pass it as a parameter but when I want to render my handlebars template, the assigned object is null.
userObj is null, even when trying this code
var userObj = users.find(u => u.id === req.params.id);
but I think the database is not wrong. Where did I made a mistake =?
Pretty sure that req.params.id is a String. Try :
const userObj = users.find(u => u.id === Number(req.params.id));
When you have a doubt about it :
console.log(
`First value : ${v1} - ${typeof v1}`,
`Second value : ${v2} - ${typeof v2}`,
);
Please replace
if (currentUser.id === req.params.id)
with
if (currentUser.id == req.params.id)
Since req.params.id is a string and and currentUser.id is a number, they cannot be compared strictly .
However a non-strict comparison should work fine.
console.log(userObj); // returns undefined
is called after the readFile callback, this is an asynchronous non-blocking event!
You have to move your:
res.render('users', {
user: userObj
});
at the end of readFile function