Async promise not returning result - javascript

How come I do not get a value in my res after the promise resolves?
My console.log looks something like this:
=====!!USER NOT FOUND!!=====
Res: undefined
This is my function
async function findUser(userID, userType) {
await new Promise((resolve, reject) => {
usersTable.findOne (
{ _id: userID }
,function (err, data) {
if (err) {
throw new Error('findUser: ' + err);
} else {
if (!data) {
console.log("=====!!USER NOT FOUND!!=====")
resolve("NEW");
} else {
console.log("=====USER FOUND=====")
resolve("OK");
};
};
});
})};
This is my caller
async function main() {
var res = "";
try {
// Find the user
res = await findUser(userEmail, "tenant");
console.log("Res: " + res );
if (res == "NEW") {
res = await newUser(); // Add the new tenant
}
}
catch(err) {
console.error(err);
console.log(" newBooking: " + err);
callback( { error:true, err } );
}
}
main();

find User should return sth:
async function findUser(userID, userType) {
return await new Promise((resolve, reject) => {
...
});
}
If you do await findUser() youre waiting until the async function returns sth. Your async function returns undefined.
By the way: You might not use an async function at all:
function findUser(userId,userType){
return new Promise(...);
}

Related

How do I return a value for a non promise callback inside an async fucntion

In below Node.js function, how do I return data.QueueUrl, so that a caller can get the value with
var url = await createSubscription('foo', req);
This is the function
async function createSubscription(name, req){
var params = {
QueueName: name,
Attributes: {
'ReceiveMessageWaitTimeSeconds': '20', // long polling wait time
}
};
sqs.createQueue(params, function(err, data) {
if (err) {
logger.error("createQueue error : " + err, req);
} else {
logger.log("queue " + name + ' created', req);
return data.QueueUrl;
}
});
}
Best practice is to wrap problematic functions at the lowest possible level, and then never call them directly again - MDN
For you this means doing the following:
function createQueue(params) {
return new Promise((resolve, reject) => {
sqs.createQueue(params, (err, data) => err ? reject(err) : resolve(data));
});
}
After that you can work with createQueue instead of sqs.createQueue:
async function createSubscription(name, req) {
const params = {
QueueName: name,
Attributes: {
'ReceiveMessageWaitTimeSeconds': '20', // long polling wait time
}
};
try {
const data = await createQueue(params);
logger.log("queue " + name + ' created', req);
return data.QueueUrl;
} catch (err) {
logger.error("createQueue error : " + err, req);
// you'll probably want to re-throw here unless the caller knows
// that an undefined return value means an error has occurred
}
}
Without all the additional log statements, the function can also look like this:
async function createSubscription(name, req) {
const params = {
QueueName: name,
Attributes: {
'ReceiveMessageWaitTimeSeconds': '20', // long polling wait time
}
};
const data = await createQueue(params);
return data.QueueUrl;
}
Since we don't use a try/catch the error/rejected promise bubbles up to the caller.
Since all the SQS functions are in the style sqs.function(params, callback) (see documentation), you could also write a more general helper that works on all the SQS functions.
function sqsPromise(sqsFnName, params) {
return new Promise((resolve, reject) => {
sqs[sqsFnName](params, (err, data) => err ? reject(err) : resolve(data));
});
}
Which allows you to do:
const data = await sqsPromise("createQueue", params);
The function doesn't need to be async to create and return a promise:
function createSubscription (name, req) {
return new Promise((resolve, reject) => {
const params = {
QueueName: name,
Attributes: {'ReceiveMessageWaitTimeSeconds': '20'}
};
sqs.createQueue(params, (err, data) => {
if (err) {
logger.error('createQueue error : ' + err, req);
reject(err);
} else {
logger.log('queue ' + name + ' created', req);
resolve(data.QueueUrl);
}
});
});
}
const url = await createSubscription('foo', req);
You could make your function to return a Promise and resolve and reject the required data according to your logic. The other way is to promisfy your callback using the util module.
Write your function like this to return a promise
async function createSubscription(name, req){
try{
const params = {
QueueName: name,
Attributes: {
'ReceiveMessageWaitTimeSeconds': '20', // long polling wait time
}
};
let data = await sqs.createQueue(params).promise();
return data;
}
catch(err){
logger.error("createQueue error : " + err.message);
}
}
And call it like this to receive the value
const url = await createSubscription('foo', req);
console.log(url.QueueUrl); // You'll get the result in url variable.

How to console reject resolve message in postman using node js

How can be resolve executed in multiple function.
As I have multiple promise function and each function contain resolve message but don't how to print this on postman
If there is single function with promise then resolve message easily get executed but what if there is function of function then how can it be possible ?
Is this possible way to return resolve or reject message from one function to another?
As I am writing to pass resolve message in postman whenever my task is completed or reject message when there is some error
But after after writing return it still not returning the resolve message or reject message inside Postman
any idea how this can be resolve?
async function readFile(filePath) {}
async function getAllFile(filePath) {
const paths = await readFile(filePath);
}
async function filterFiles(filePath) {
const paths = await getAllFile(filePath);
}
function addDocument(data){
return new Promise((resolve, reject) => {
Document.create({
name: data.name,
},
}).then(function (filePath) {
filterFiles(filePath);
let msg = "Document created Succesfully";
return resolve(msg);
})
.catch(function (err) {
return reject("Can't be updated please try again :) " + err);
});
});
}
function updateDoc(data){
return new Promise((resolve, reject) => {
Document.update({
name: data.name,
}
where: {
product_id: data,
},
})
}).then(function (filePath) {
getAllFile(filePath);
let msg = "Updated Successfully";
return resolve(msg);
})
.catch(function (err) {
return reject("Can't be updated please try again :) " + err);
});
}
function findDoc(data){
return new Promise((resolve, reject) => {
Document.findAll(
{
raw:true,
},
{
name: data.name,
}
where: {
product_id: data,
},
})
}).then(function (product) {
if(product.length===0){
addDocument(product);
let msg="task completed";
return resolve(msg,product);
else{
return resolve(updateDoc(product));
}
})
.catch(function (err) {
return reject("Can't be updated please try again :) " + err);
});
}
function findDoc(data){
return new Promise((resolve, reject) => {
Document.findAll(
where: {
product_id: data.id,
},
})
}).then(function (product) {
findDoc(product);
let msg="task completed";
return resolve(msg,product);
})
.catch(function (err) {
return reject("Can't be updated please try again :) " + err);
});
}
How can i get resolve message in postman
It's hard for me to test your codes but it's quite possible to return resolve, reject messages in the response object.
If you want to pass a reject message through 3 promise for example and return a response you need use try, catch blocks, you can check this example:
// index.js
const express = require('express')
const app = express()
const port = 3000
const responder1 = (error, message) => {
return new Promise((resolve, reject) => {
if (error) {
reject(error);
return;
}
resolve(message);
});
};
const responder2 = (error, message) => {
return new Promise((resolve, reject) => {
if (error) {
reject(error);
return;
}
resolve(message);
});
};
const responder3 = (error, message) => {
return new Promise((resolve, reject) => {
if (error) {
reject(error);
return;
}
resolve(message);
});
};
app.use('/', async (req, res) => {
let result;
try {
const error = new Error("This is a error message.");
result = await responder1(error, null);
} catch (error1) {
try {
await responder2(error1, null);
} catch (error2) {
try {
await responder3(error2, null)
} catch (error3) {
res.send({
success: 0,
message: error3.message
});
return;
}
}
}
res.send({
success: 0,
message: result
});
});
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
})
And if you want to pass resolve message:
const express = require('express')
const app = express()
const port = 3000
const responder1 = (error, message) => {
return new Promise((resolve, reject) => {
if (error) {
reject(error);
return;
}
resolve(message);
});
};
const responder2 = (error, message) => {
return new Promise((resolve, reject) => {
if (error) {
reject(error);
return;
}
resolve(message);
});
};
const responder3 = (error, message) => {
return new Promise((resolve, reject) => {
if (error) {
reject(error);
return;
}
resolve(message);
});
};
app.use('/', async (req, res) => {
let result = await responder3(null, await responder2(null, await responder1(null, "This is a test message.")));
res.send({
success: 0,
message: result
});
});
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
})

async function not getting result

I am trying to get the result of an async function in my calculateOrderAmount function but it returns undefined.
The console.log in the called function returns the good result, but inside calculateOrderAmount, I get undefined. Here is my code:
getMultiStrats = async () => {
await MultiStrats.findOne({}, (err, multiStrats) => {
if (err) {
return err
}
if(!multiStrats) {
return console.log('MultiStrat not found')
}
console.log('returns MultiStrat: ' + multiStrats)
return multiStrats
})
.catch(err => console.log(err))
}
async function calculateOrderAmount(balance, ticker){
const multiState = await StrategyController.getMultiStrats().catch((err) => console.log(err))
console.log('multiState: ' + multiState)
some logic
}
Here is the console log:
multiState: undefined
returns MultiStrat: {
_id: 5ff73c74d1135b39fc709b80,
positionsCount: 1,
inTradeCount: 0,
__v: 0
}
What did I miss? Thanks you very much for your time!
The current approach is pretty unclear--there's no need for .catch, async, await all at once. return multiStrats returns from the inside of the callback, not from getMultiStrats. The async/await on getMultiStrats is superfluous, just adding another promise wrapper that doesn't accomplish anything.
Given that findOne as shown here uses a callback rather than a promise, you can either use callbacks all the way or you can promisify findOne as follows, using .then and .catch in the caller:
const MultiStrats = {
findOne: (obj, cb) => cb(null, "I'm a multistrat!")
};
const StrategyController = {
getMultiStrats: () => new Promise((resolve, reject) =>
MultiStrats.findOne({}, (err, multiStrats) => {
if (err) {
return reject(err);
}
else if (multiStrats) {
return resolve(multiStrats);
}
reject(Error("Multistrat not found"));
})
)
};
const calculateOrderAmount = (balance, ticker) =>
StrategyController
.getMultiStrats()
.then(multiState => {
console.log('multiState: ' + multiState)
// some logic
})
.catch(err => console.error(err))
;
calculateOrderAmount();
Or use async/await and try/catch:
const MultiStrats = {
findOne: (obj, cb) => cb(null, "I'm a multistrat!")
};
const StrategyController = {
getMultiStrats: () => new Promise((resolve, reject) =>
MultiStrats.findOne({}, (err, multiStrats) => {
if (err) {
return reject(err);
}
else if (multiStrats) {
return resolve(multiStrats);
}
reject(Error("Multistrat not found"));
})
)
};
const calculateOrderAmount = async (balance, ticker) => {
try {
const multiState = await StrategyController.getMultiStrats();
console.log('multiState: ' + multiState)
// some logic
}
catch (err) {
console.error(err);
}
};
calculateOrderAmount();
If this is MongoDB's findOne and already returns a promise, then you can just return the promise to the caller, optionally awaiting it and throwing for the null result:
const MultiStrats = {
findOne: async query => "I'm a multistrat!"
};
const StrategyController = {
getMultiStrats: async () => {
const result = await MultiStrats.findOne({});
if (result) {
return result;
}
throw Error("Multistrat not found");
}
};
const calculateOrderAmount = (balance, ticker) =>
StrategyController
.getMultiStrats()
.then(multiState => {
console.log('multiState: ' + multiState);
// some logic
})
.catch(err => console.error(err))
;
calculateOrderAmount();
You cannot return values from an inner callback and reach the outer function, I would suggest
1- only use promises
2- wrap your code with promise to be sure that await will return the async result the way you expect to have.
getMultiStrats = async () => {
return new Promise((resolve, reject) => {
MultiStrats.findOne({}, (err, multiStrats) => {
if (err) {
return err
}
if (!multiStrats) {
console.log('MultiStrat not found')
reject('MultiStrat not found')
}
console.log('returns MultiStrat: ' + multiStrats)
resolve(multiStrats);
})
.catch(err => {
console.log(err);
reject(err)
})
})
}
async function calculateOrderAmount(balance, ticker) {
try {
const multiState = await StrategyController.getMultiStrats()
console.log('multiState: ' + multiState)
// some logic
} catch (error) {
console.error(error);
}
}
Assuming that you use mongoose. I suggest using the promise interface like described in the documentation.
const getMultiStrats = async () => {
const query = MultiStrats.findOne({});
let multiStrats;
try {
multiStrats = await query.exec();
} catch (error) {
return error;
}
if (multiStrats) {
console.log("returns MultiStrat: " + multiStrats);
} else {
console.log("MultiStrat not found");
}
return multiStrats;
}
I would personally not return the error, but instead just let the error be thrown. With the above code the caller of getMultiStrats has to figure out if there return value is the expected result or an error. If you don't catch the error, it is thrown further up to the caller.
const getMultiStrats = async () => {
const multiStrats = await MultiStrats.findOne({}).exec();
if (multiStrats) {
console.log("returns MultiStrat: " + multiStrats);
} else {
console.log("MultiStrat not found");
}
return multiStrats;
}
You can further simplify this if you where to leave the console.log of of the equation.
const getMultiStrats = () => MultiStrats.findOne({}).exec();

NodeJS: Can't return a result from a function

I'm trying to return the result from this function :
var YouTube = require('youtube-node');
var youTube = new YouTube();
youTube.setKey('XXXXXXXXXXXX');
var result = youTube.search('World War z Trailer', 2,
function(error, result) {
if (error) {
console.log(error);
} else {
return result
}})
console.log(result)
But then I only get undefined as a result in console.
You need to wait for the response.
This simple answer is to place the console.log(result) inside the callback.
Or you can wrap the search method in a promise:
var promise = new Promise((resolve, reject) => {
youTube.search('World War z Trailer', 2, function (error, result) {
if (error) {
reject(error);
}
else {
resolve(result);
}
})
});
Then you can wait for the response using .then() like this:
promise.then((result) => {
console.log(result);
}).catch((err) => {
console.error(err);
});
Or using await/async:
(async () => {
try {
const result = await promise;
console.log(result);
} catch (err) {
console.error(err)
}
})();
Last function here is a callback function, it doesn't return value in way you want. Read how it works somewhere, for example here.
Your issue could be resolved with Promise in this way
var search = new Promise(
(resolve, reject) => {
youTube.search('World War z Trailer', 2, function(error, result) {
if (error) { reject(error); }
resolve(result);
})
}
);
(async () => {
var result = await search;
console.log(result);
})()

Alexa SDK + NodeJS : Promise Chaining

I am using AWS lambda function with NodeJS for my alexa skill. But I am stuck in using async function.
Here is the requirement
On launching, a asynchronous function function1 is called
After the completion of function1, the result is passed to async function2.
The result of function2 should be spoken out to user
So I am trying to solve this by using Promise chaining. Below is my pseudocode
function function1() {
return new Promise((resolve, reject) => {
//some async operation
if (result1) {
resolve(result1);
} else {
reject(error);
}
});
}
function function2(result1) {
return new Promise((resolve, reject) => {
//some async operation
if (result2) {
resolve(result2);
} else {
reject(error);
}
});
}
const mainHandler = {
'LaunchRequest': function () {
function1()
.then(result1 => function2(result1))
.then(result2 => {
//succcess
this.response.cardRenderer(result2);
this.response.speak(result2);
this.response.listen(config.HELP_REPROMPT);
this.emit(':responseReady');
}).catch(err => {
//error
this.response.cardRenderer(err);
this.response.speak(err);
this.response.listen(config.HELP_REPROMPT);
this.emit(':responseReady');
});
},
};
Now the issue I am facing is that alexa terminates prematurely after first function execution without waiting for function2 to be executed. Not sure what I am doing wrong here. Any help would be appreciated. Thanks in advance.
Note: If there is only one async function then it works fine. i.e below code works fine.
const mainHandler = {
'LaunchRequest': function () {
function1()
.then(result1 => {
//succcess
this.response.cardRenderer(result1);
this.response.speak(result1);
this.response.listen(config.HELP_REPROMPT);
this.emit(':responseReady');
})
.catch(err => {
//error
this.response.cardRenderer(err);
this.response.speak(err);
this.response.listen(config.HELP_REPROMPT);
this.emit(':responseReady');
});
},
};'
Issue is when 2 async functions are involved
See if this helps:
function function1() {
return new Promise((resolve, reject) => {
//some async operation
if (result1) {
resolve(result1);
} else {
reject(error);
}
});
}
function function2(result1) {
return new Promise((resolve, reject) => {
//some async operation
if (result2) {
resolve(result2);
} else {
reject(error);
}
});
}
const ErrorHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& handlerInput.requestEnvelope.request.intent.name === 'LaunchRequest';
},
async handle(handlerInput, error) {
result1 = await function1();
result2 = await function2(result1);
/* rest of code according to version2 */
},
};
For v1 and v2 sdk difference click here.

Categories