Return not stopping function - node.js

I have the following code
insertcontact(root, args) {
var finalresult = '';
var soap = require('soap');
var url = 'http://192.168.100.2/setlead/webservice.asmx?wsdl';
var soapargs = {
contacto: args.contacto, token: args.token, PrimeiroNome: args.PrimeiroNome, Apelidos: args.Apelidos, Email: args.Email, Telefone: args.Telefone, Origem: args.Origem
};
soap.createClient(url, function (err, client) {
if (err) {
console.log(err);
finalresult = err
return { contacto: "error cliente" };
}
else {
client.OperationDetail(args, function (err, result) {
console.log(result);
return { token: result };
});
}
});
return {
contacto: args.contacto,
PrimeiroNome: args.PrimeiroNome,
token: args.token,
Apelidos: args.Apelidos,
Email: args.Email,
Telefone: args.Telefone,
Origem: args.Origem
};
}
}
The operation does not trigger any error and I do receive the result in the console log. But I don't receive the return declared right after that part. The function goes on and I receive the last return declared. Shouldn't it stop at the return result?

This is a classic mistake in Javascript.
The function will return even before starting to create the soap client, because of its async behavior.
That function implementation is not very good as it returns the params whatever the result of the client creation process.
It would be much better to do it like this, with embeded soap args in the return statement if needed, and of course without the last return statement:
// ...
soap.createClient(url, function (err, client) {
if (err) {
console.log(err);
finalresult = err
return { contacto: "error cliente" };
} else {
client.OperationDetail(args, function (err, result) {
console.log(result);
return {
token: result,
soapargs: soapargs
};
});
}
});

wrap your returned object in parenthesis like this
return ({
contacto: args.contacto,
PrimeiroNome: args.PrimeiroNome,
token: args.token,
Apelidos: args.Apelidos,
Email: args.Email,
Telefone: args.Telefone,
Origem: args.Origem
});

Related

Node js firebase notification return the json response in a function format

So I have the following notification function,
async function sendNotification(registrationToken, title, body) {
const message = {
to: registrationToken,
notification: {
title: title,
body: body
}
};
await fcm.send(message, (err, response) => {
if (err) {
return err;
}
else {
return response;
}
});
};
When I call the function like this in the api
let result = await sendNotification('','','');
result is always undefined. How do I solve this issue?

why does my nodejs function returning undefined?

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 });
});

wait for result from an async method

I'm trying to call an async method from for loop, but it doesn't wait for the result from that method.
Below is my code:
async function fetchActivityHandler (req, reply) {
esClient.search({
index: 'user_activity',
type: 'document',
body: {
_source : ["userId","appId","activity","createdAt","updatedAt"],
query: {
bool : {
must:[
{match : { 'userId': req.params.id }}
]
}
}
}
},async function (error, response, status) {
if (error){
console.log('search error: '+error)
}
else {
var activities = [];
//await Promise.all(response.hits.hits.map(async function(hit){
for (const hit of response.hits.hits) {
var activity = hit._source
var app = await fetchAppDetails(activity.appId);
console.log(app);
activity = {...activity,app : app}
activities.push(activity);
console.log(activity);
}
reply.status(200).send(activities);
}
});
}
async function fetchAppDetails (appId) {
esClient.get({
index: 'app',
type: 'document',
id: appId
}, function (err, response) {
console.log(response._source);
return (response._source);
});
}
What may be the problem. I'm using async and await, but it is not working.
Await works with promise. You should wrap your function with promise to get this work. Hope this will help you. Also you do not need to use async on fetchActivityHandler function. Only in the callback which you have already used.
function fetchAppDetails (appId) {
return new Promise((resolve,reject)=>{
esClient.get({
index: 'app',
type: 'document',
id: appId
}, function (err, response) {
if(err){
reject(err);
}
else{
resolve(response)
}
});
});
}

Trouble to synchronise promises in Node.js using Q

I am currently doing an API in Node.JS with the framework Sails.js. I am using promises for the first time and I have some troubles to sync my promises like I want.
My main function is the following :
createCard: function(req, res) {
checkIfUserHasStripeAccount(req.user)
.then(addCreditCardToStripeAccount())
.then(function cardCreated() {
res.send(200, {
msg: 'Card created'
});
})
.catch(function handleError(err) {
res.send(err.httpCode, err.msg);
})
},
Obviously I can't add a credit card to a stripe account if the user doesn't have one.
The function checkIfUserHasStripeAccount() checks if the account exists and if not, create it.
Here is the code for this part :
function checkIfUserHasStripeAccount(user) {
var deferred = q.defer();
if (!user.idStripe) {
createStripeAccountToUser(user)
.then(function(savedUser) {
deferred.resolve(savedUser);
})
.catch(function(err) {
deferred.reject(err);
})
} else {
deferred.resolve(user);
}
return deferred.promise;
}
function createStripeAccountToUser(user) {
var deferred = q.defer();
var jsonUserToCreate = {
description: user.firstname + ' ' + user.surname,
email: user.email
};
stripe.customers.create(jsonUserToCreate, function(err, customer) {
if (err) {
deferred.reject({
httpCode: 500,
msg: 'some error'
});
} else {
user.idStripe = customer.id;
user.save(function(err, savedUser) {
if (err) {
deferred.reject({
httpCode: 500,
msg: 'some error'
});
}
deferred.resolve(savedUser);
});
}
});
return deferred.promise;
}
The problem is that the .then(addCreditCardToStripeAccount()) is executed before checkIfUserHasStripeAccount() is finished.
I can't figure out why. I thought the .then(addCreditCardToStripeAccount()) would only be executed if it received a reject or resolve.
You are correct in your line of thought.
The problem is that you are invoking your function instead of referencing it:
.then(addCreditCardToStripeAccount())
should be:
.then(addCreditCardToStripeAccount)
I expect this to work:
createCard: function (req, res) {
checkIfUserHasStripeAccount(req.user)
.then(addCreditCardToStripeAccount)
.then(function cardCreated(){
res.send(200, {msg: 'Card created'});
})
.catch(function handleError(err) {
res.send(err.httpCode, err.msg);
})
},
For future, note that the () after the function name invokes the function, as order of execution in JS will evaluate it first due to being inside the then's ().
In promise chains, always invoke only the first function. Example:
function first () { /*...*/ } // All return promise.
function second() { /*...*/ }
function third () { /*...*/ }
first() // Invoked
.then(second) // Not invoked. second() will have been bad here.
.then(third);

Check if user already exist and wait for callback

I have a small function to validate the user input. In that function I will also check if the email address is already taken. But I have some trouble with the async callback.
I hope anyone could give me a hint, how I could solve this. I use nodejs with the express 3 framework, mongodb and the node-validator library.
This is a part of my validation function:
function check(data, callback) {
mongoose.model('User', User).count(data, function (err, count) {
callback(err, !! count);
});
};
function validate(email, password, confirm) {
var v = new Validator(),
errors = new Array();
v.error = function (msg) {
errors.push(msg);
};
check({email: email}, function (err, exists) {
v.check(exists, { email: 'E-Mail is already taken' }).equals(false);
});
...
return errors;
}
Based on the async callback the variable errors is at the return statement empty. How could I else check if the email address is already in the databse?
You are going to have to add a callback to your validate function. As it stands now, your check function is asynch so you are immediately returning the empty errors array.
function check(data, callback) {
mongoose.model('User', User).count(data, function (err, count) {
callback(err, !! count);
});
};
function validate(email, password, confirm, callback) {
var v = new Validator(),
errors = new Array();
v.error = function (msg) {
errors.push(msg);
};
check({email: email}, function (err, exists) {
if (err) {
return callback(err);
}
v.check(exists, { email: 'E-Mail is already taken' }).equals(false);
callback(null, v);
});
};
// Calling to validate example
server.get("/validate_user_or_whatever", function(req, resp) {
// Call validate with callback
validate(req.param("email"), req.param("password"), true, function(err, validator) {
if (err) {
return resp.json({success: false, message: err.message});
}
var success = validator.isValid; // or something
// Respond with the results
resp.json({success: success});
});
});
Now, your next question is probably going to be how do I run all these validate functions and wait for them to return before calling the validate callback. Good question, take a look at the async module.
You need to think async and pass callbacks that will be called asynchronously.
Quick example:
app.get('/blah', function(req, res) {
// Whatever
validate(email, pass, confirm, function(errors) {
if (errors.length == 0)
resp.send(200, 'blah');
else
resp.send(400, 'blah blah');
});
})
function validate(email, password, confirm, callback) {
var v = new Validator(),
errors = new Array();
v.error = function (msg) {
errors.push(msg);
};
check({email: email}, function (err, exists) {
v.check(exists, { email: 'E-Mail is already taken' }).equals(false);
}, function() {
callback(errors);
});
// ...
return errors;
}

Resources