why does my nodejs function returning undefined? - node.js

function getUserByStudentId(NIM) {
db.query('SELECT * FROM data_admin WHERE id_mahasiswa = ?', [NIM], async (err, result) => {
if (!result) {
return null
} else {
var data = await {
id: result[0].id_Admin,
email: result[0].email,
jabatan: result[0].jabatan,
password: result[0].password,
id_mahasiswa: result[0].id_mahasiswa,
id_Acara: result[0].id_Acara,
id_Organisasi: result[0].id_Organisasi
}
console.log(data) // there is a value here
return data
}
})
}
console.log(getUserByStudentId('1301194051')) // undefined returned
I'm a student and start learning nodejs. Would you explain to me, why my function returning undefined
console.log(getUserByStudentId('1301194051')) // undefined
but when I console.log on the function I got returned value

I'll promisify the function for you:
function getUserByStudentId(NIM) {
return new Promise(function(resolve, reject) => {
db.query('SELECT * FROM data_admin WHERE id_mahasiswa = ?', [NIM], (err, result) => {
if (!result) {
resolve(null);
} else {
var data = {
id: result[0].id_Admin,
email: result[0].email,
jabatan: result[0].jabatan,
password: result[0].password,
id_mahasiswa: result[0].id_mahasiswa,
id_Acara: result[0].id_Acara,
id_Organisasi: result[0].id_Organisasi
}
console.log(data) // there is a value here
resolve(data);
}
});
});
}
If you're going to use this function in global scope, use then:
getUserByStudentId('1301194051').then(result => {
console.log(result);
});
If you want to use this function inside an async function, you can await the result:
async function doSomethingWithUser(NIM) {
const user = await getUserByStudentId(NIM);
}
For example, if you're using express:
app.get('/user/:id', async (res, req) => {
const NIM = req.param.id;
const user = await getUserByStudentId(NIM);
res.json({ user });
});

Related

problem in sending base64 data in GET request

Hi I am facing issues sending base64 data in GET request.
I was successful in converting the image into base64 data and inserting it in receivedFile
but during response the attachments come as an empty array while the rest of the data i.e user_id is flowing successfully.
Hence if you could please help me to resolve this issue.
Below is the code
router.js
router.get('/users/data/expand/:nid',async (req,res) => {
var idselected = req.params.nid;
var dir = '\images';
var receivedFile = [];
try {
const checkData = await user.find({"user_id": idselected});
await checkData[0].attachments.forEach (element => {
fs.readdir(dir,function(err,files) {
if(err) {
console.log(err)
}else {
files.forEach((filename) => {
filename = element;
fs.readFile(filename,'base64', (err,base64Data) => {
if(err) {
console.log(err);
}
receivedFile.push(base64Data);
})
})
}
})
})
//issue is here the attachments is coming as empty instead of base64 data
const returnUser = new User({
user_id: checkData.user_id,
attachments: receivedFile
})
res.status(201).send(returnUser);
}
catch(e) {
res.status(500).send(e)
}
})
Well its always good to create helper functions and to promisfy it so you can use async / await syntax.
I have changed your code. I didnt tested it but i guess it should work:#
router.get("/users/data/expand/:nid", async (req, res) => {
var idselected = req.params.nid;
var dir = "images";
try {
const checkData = await user.findOne({ user_id: idselected });
let receivedFile = await Promise.all(
checkData.attachments.flatMap(async element => {
let files = await readDirectory(dir);
return await Promise.all(
files.map(filename => {
filename = element;
return readFile(filename)
})
);
})
);
const returnUser = new User({
user_id: checkData.user_id,
attachments: receivedFile
});
let savedUser = await returnUser.save();
res.status(201).send(savedUser);
} catch (e) {
res.status(500).send(e);
}
});
function readDirectory(dir) {
return new Promise((res, rej) => {
fs.readdir(dir, function(err, files) {
if (err) {
rej(err);
} else {
res(files);
}
});
});
}
function readFile(filename) {
return new Promise((res, rej) => {
fs.readFile(filename, "base64", (err, base64Data) => {
if (err) {
rej(err);
}
res(base64Data);
});
});
}
I guess you use mongoose.
There is an method called findOne and also you forgot to save your model with returnUser.save()

AdonisJS unable to return response within a function (SAP HANA)

I am using SAP HANA CLIENT for NodeJS in my AdonisJS project. I am unable to return the response as json from the the function that connects to the database. Here is the code
The controller method validateInvoice is first called
async validateInvoice({request, response}) {
const req = request.all()
const inv_num = req.invoice_num;
const data = await this.fetchInvStatus(inv_num);
return response.json({success: true, data: data});
}
This in turn calls the fetchInvStatus method which actually connects to HANA DB
var conn = hana.createConnection();
var conn_params = {
serverNode: '127.0.0.1:30015',
uid: 'CUST_USER_ROLE_ADMIN',
pwd: 'Welcome#1234',
database: 'DED'
};
conn.connect(conn_params, (err) => {
if(err) {
return err;
}
conn.exec("Select * FROM SAPDED.YACSF_RRHD where INVOICE_NUMBER = ?", ['BOMT000005'], (err, result) => {
if (err) {
return err;
}
console.log(result);
return result;
})
});
In the console I'm able to see the result but this result is not being passed to the validateInvoice method so that the API could return the response.
The line in the first method response.json() is executed even before the data from DB is returned. How can I overcome this problem? I've tried adding return statement to conn.connect and conn.exec but nothing helps!
You have to return promise in the fetchInvStatus method.
function fetchInvStatus() {
return new Promise(resolve, reject) {
var conn = hana.createConnection();
var conn_params = {
serverNode: '127.0.0.1:30015',
uid: 'CUST_USER_ROLE_ADMIN',
pwd: 'Welcome#1234',
database: 'DED'
};
conn.connect(conn_params, (err) => {
if(err) {
reject(err);
}
conn.exec("Select * FROM SAPDED.YACSF_RRHD where INVOICE_NUMBER = ?", ['BOMT000005'], (err, result) => {
if (err) {
reject(err);
}
console.log(result);
resolve(result);
})
});
}
}

Firebase function not returning data

I'm trying to get data from my Firebase function, but it keeps returning a null response. It looks like I need to return a promise and return my data in that promise, but I can't seem to get it to work even though I think I'm doing that. I'm not the most familiar with Node.JS, so I might be returning the wrong things in the promise.
Here's my function code:
exports.tasksLists = functions.region('us-east1').https.onCall((data) => {
const userDoc = db.collection('users').doc(data.text);
return userDoc.get().then((doc) => {
if (!doc.exists) {
return "";
} else {
return doc.data().tasksKey;
}
}).then((tasksCreds) => {
const oauth2Client = new google.auth.OAuth2(
'444701140384-srcttdrg28geg598h65dkekad47u9a48.apps.googleusercontent.com',
'wNL4ZrBGYOnXUMvEcE7Z_Smo',
'https://collag-oauth-u5b2i5chyq-ue.a.run.app/classroomcallback'
);
oauth2Client.setCredentials({
refresh_token: tasksCreds.refresh_token,
access_token: tasksCreds.token
});
const service = google.tasks({ version: 'v1', auth: oauth2Client });
return service.tasklists.list({}, (err, res) => {
if (err) {
functions.logger.error(new Error(err));
return JSON.stringify(err);
}
const lists = res.data.items;
if (lists) {
functions.logger.info(lists);
return lists;
} else {
functions.logger.info('no lists');
return "No lists";
}
});
})
.catch((e) => {
functions.logger.error(new Error(e));
return JSON.stringify(e);
});;
});
I've also tried putting the OAuth and API request in the first .then() under else but that didn't work either.
Here's my frontend code to call the function and handle the data:
let tasksLists = fireApp.functions('us-east1').httpsCallable('tasksLists');
tasksLists({ text: currentUser.uid }).then(function (result) {
if (!result.data) {
console.log('no data');
}
let lists = result.data;
console.log(lists);
});
The console.log(lists) just outputs null.
The problem is that you're not returning a promise. You can use the Promise constructor, passing in the resolve/reject parameters and call any of those when your want to return the asynchronous result. Change your cloud function like so:
exports.tasksLists = functions.region('us-east1').https.onCall((data) => {
const userDoc = db.collection('users').doc(data.text);
return new Promise((resolve, reject) => {
userDoc.get().then((doc) => {
if (!doc.exists) {
return "";
} else {
return doc.data().tasksKey;
}
}).then((tasksCreds) => {
const oauth2Client = new google.auth.OAuth2(
'444701140384-srcttdrg28geg598h65dkekad47u9a48.apps.googleusercontent.com',
'wNL4ZrBGYOnXUMvEcE7Z_Smo',
'https://collag-oauth-u5b2i5chyq-ue.a.run.app/classroomcallback'
);
oauth2Client.setCredentials({
refresh_token: tasksCreds.refresh_token,
access_token: tasksCreds.token
});
const service = google.tasks({ version: 'v1', auth: oauth2Client });
service.tasklists.list({}, (err, res) => {
if (err) {
functions.logger.error(new Error(err));
// return JSON.stringify(err);
reject(err);
}
const lists = res.data.items;
if (lists) {
functions.logger.info(lists);
resolve(lists);
// return lists;
} else {
functions.logger.info('no lists');
resolve("No lists")
// return "No lists";
}
});
})
.catch((e) => {
functions.logger.error(new Error(e));
reject(e);
// return JSON.stringify(e);
});
})
});

Mongoose .select is not a function when using with Azure Function

I'm trying to use mongoose .select operator with my azure function but it keeps saying TypeError: db.collection(...).findOne(...).select is not a function at db.collection.find.toArray
It returns the user's data in the console, but doesn't filter it down with .select
Why is that?
var MongoClient = require('mongodb').MongoClient;
var Post = require('./model/post');
var mongoose = require('mongoose');
module.exports = async function (context, req) {
let currentPage = 1;
MongoClient.connect(process.env.CosmosDBConnectionString, async (err, client) => {
let send = response(client, context);
if (err) send(500, err.message);
let db = client.db(process.env.dbName);
await db.collection('listings').find(
{
$and: [
{ winnerHasBeenNotified: false },
{ auctionEndDateTime: { $lte: Date.now().toString() } }
]
}
)
.toArray((err, result) => {
console.log("result");
console.log(result);
if (result) {
for (let i = 0; i < result.length; i++) {
db.collection('users').findOne(
{
_id: mongoose.Types.ObjectId(result[i].bidderId)
}
).select("notificationBy").toArray((err, result) => {
console.log("USER RESULT!");
console.log(result);
});
}
}
if (err) send(500, err.message);
send(200, JSON.parse(JSON.stringify(result)));
});
});
};
function response(client, context) {
return function (status, body) {
context.res = {
status: status,
body: body
};
client.close();
context.done();
};
}
find() returns a cursor, which has a select method. findOne() retrieves a single document and returns a promise if no callback is provided.
If you are trying to get just the "notificationBy" field, try passing the fields option to findOne.

resolving a promise using mongodb and nodejs

Hello I am new to nodejs and mongodb, i am having trouble resolving my first promise after the second promise has been resolved. I can see the result of my second promise after it is resolved. Here is my code
var getShows = function () {
return new Promise(function (resolve, reject) {
usersdb.find(function (err, result) {
if(err) return console.error(err);
var usersFromCall = result;
var task = function (users) {
return new Promise(function (resolve, reject) {
var user = {
'name': '',
'pages': []
}
user.name = users.show;
console.log(users);
pagedb.find({'show' : user.name}, function (err, resp) {
for(var j = 0 ; j <resp.length; j ++){
var pages = { 'pageId': ''};
pages.pageId = resp[j].pageId;
user.pages.push(pages);
}
console.log(user);
resolve({show: user});
})
});
};
var actions = usersFromCall.map(task);
return Promise.all(actions);
}).then(function () {
resolve()
})
});
};
do i resolve the first promise in a then function after the find?
The following should work:
var getShows = function () {
return new Promise(function (resolve, reject) {
usersdb.find(function (err, users) {
if (err) return console.error(err);
var task = function (user) {
return new Promise(/* ... */);
};
var actions = users.map(task);
Promise.all(actions).then(resolve, reject);
});
});
};
getShows().then(function (results) {
// Prints the result of each task as an array
console.log(results);
});
Looking at your code, it seems .find returns a Promise. So, just for the sake of avoiding the Promise constructor anti-pattern please try the following, I believe it will produce the correct result
var getShows = function() {
return usersdb.find()
.then(result =>
Promise.all(result.map(
users =>
pagedb.find({
show: users.show
})
.then(resp => ({
show: {
name: users.show,
pages: resp.map(item => ({pageId: item.pageId}))
}
}))
)
)
);
};
or the ES5 version
var getShows = function getShows() {
return usersdb.find().then(function (result) {
return Promise.all(result.map(function (users) {
return pagedb.find({
show: users.show
}).then(function (resp) {
return {
show: {
name: users.show,
pages: resp.map(function (item) {
return { pageId: item.pageId };
})
}
};
});
}));
});
};

Resources