simple async function in javascript - javascript

I'm playing with async/await and with the code below, shouldn't response be empty or null until the setTimeout in the response const has finished after 5 seconds? and shouldn't response return xyz instead of 1?
async function test() {
try {
const response = await setTimeout(
function() {
const obj = {};
obj.text = "xyz";
console.log('should console log after 5 seconds')
return obj;
},
5000)
if (response) {
console.log(`response is ${response}`)
console.log(`response.text is ${response.text}`)
}
}
catch(err) {
console.log(err)
}
}
test();

You have to put a Promise to await the setTimeout().
async function test() {
try {
const response = await new Promise((resolve) => {
setTimeout(
function() {
const obj = {};
obj.text = "xyz";
console.log('should console log after 5 seconds')
return resolve(obj);
},
5000)
});
if (response) {
console.log(`response is ${response}`)
console.log(`response.text is ${response.text}`)
}
}
catch(err) {
console.log(err)
}
}
test();

For your code to work as per the expectations, you need to wrap the set timeout in a promise. Check the snippet. Without wrapping it in promise, setTimeout returns value immediately which is the ID value of the timer.
async function test() {
try {
const response = await new Promise(function(resolve, reject) {
setTimeout(
function() {
const obj = {};
obj.text = "xyz";
console.log('should console log after 5 seconds')
resolve(obj);
},
5000)
})
if (response) {
console.log(`response is ${response}`)
console.log(`response.text is ${response.text}`)
}
} catch (err) {
console.log(err)
}
}
test();

Related

How do I call an async await function with delay interval ("Timeout"?) every 4 seconds?

I need to call a function every 4 seconds once, I figured I must use timeout, but I am not sure how to implement it with the async await
Here is my function code:
exports.sendWhatsappMessage = async (data) => {
// Get > WhatsApp Client
let client = wwjsInstances.getInstance(data.client_id)
// Send > WhatsApp Message
await client.sendMessage((data.recipient +'#c.us'), data.message).then(() => {
console.log('DONE');
});
// Result Object
let result = {
ok: true,
params: data,
message: `[WhatsApp] : Task ${data.client_id}: Succeeded`
}
// Success
return result;
};
I tried adding timeout to the promise but I am getting the error TypeError: resolve is not a function:
exports.sendWhatsappMessage = async (data) => {
let client = wwjsInstances.getInstance(data.client_id)
function timeout(ms) {
client.sendMessage((data.recipient +'#c.us'), data.message).then(() => {
console.log('DONE');
});
let myPromise = new Promise(function(resolve) {
resolve(client)
});
// let something = await myPromise;
return await myPromise;
}
async function sleep(fn, ...args) {
await timeout(3000);
return fn(...args);
}
let randomInterval = parseInt(((Math.random() * (0.5 - 1.0) + 1.0) * 10000))
await timeout(randomInterval);
let result = {
ok: true,
params: data,
message: `[WhatsApp] : Task ${data.client_id}: Succeeded`
}
// Success
return result;
};
function timeoutPromise(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
const yourLogic = async() => {
// your logic
await CommonUtility.timeoutPromise(1001)
// continue the logic after the timeout
}

How to use the result of .then function to another function in js?

Please help I want to use the result of function 1 (Fn1) in function 2 (Fn2).
App={
st: null,//st is number value
Fn1: function() {
App.contracts.contractName.deployed().then(function(instance){
return instance.getST();
}).then(function(result){
App.st = result;
});
},
Fn2: function() {
alert(App.st)//
}
}
You need to call Fn1 before Fn2 to access it's value, so let's wrap Fn1 into Promise:
App = {
st: null,//st is number value
Fn1: function() {
return new Promise((resolve, reject) => {
App.contracts.contractName.deployed().then(function(instance){
return instance.getST();
}).then(function(result){
App.st = result;
resolve();
}).catch(function(err){
reject(err);
})
})
},
Fn2: function() {
alert(App.st)
}
}
or better with async/await:
App = {
st: null,//st is number value
Fn1: async function() {
try {
const instance = await App.contracts.contractName.deployed();
const result = await instance.getST();
App.st = result;
} catch(err) {
throw err;
}
},
Fn2: function() {
alert(App.st)
}
}
Now you can wait until Fn1 exec before calling Fn2:
App.Fn1().then(function() {
App.Fn2()
})
or using async/await:
await App.Fn1()
App.Fn2()
You can just return the Promise defined in Fn1
Fn1: function() {
return App.contracts.contractName.deployed().then((instance) => {
return instance.getST();
}).then((result) => {
// Note that we return the assignment
return App.st = result;
});
}
Then you have two options, either you can call Fn1 before Fn2
App.Fn1().then(st => App.Fn2());
Or you can adjust Fn2's implementation to call Fn1 first.
// simplistic solution
Fn2: function() {
App.Fn1().then(st => {
// do something with st
});
}
// more robust solution
Fn2: function() {
const resolveST = () => App.st != null ? Promise.resolve(App.st) : App.Fn1();
resolveST().then(st => {
// do something with st
})
}
Then using Fn2 is as simple as App.Fn2()

Await inside loop before move to another iteration

I am trying to send message through an API using a function. When function do his duty it returns back a value which is messageLodId and it needs to be updated at Attendence in main loop. But when I execute this code, value comes undefined.
There are two questions:
1) Is the structure right?
2) If yes, please provide the answer for this problem.
//Posting SMS
router.post('/sms/', async function(req, res) {
let attendenceRecordId = parseInt(req.body.attendenceRecordId);
let result = await AttendenceRecord.findOne({where: {id: attendenceRecordId }, include: [ {model: Attendence, include: [{model: Student}
]}, {
model: Class
}], order: [['date', 'DESC']]});
if(!result) {
res.sendStatus(404);
}
for await (let attendence of result.attendences){
let messageLogId = await sendSMS(attendence);
console.log("Message ID: ", messageLogId);
Attendence.update(
{ smsLogId: messageLogId },
{ where: { id: attendence.id } }
);
}
AttendenceRecord.update(
{ isMessageSent:true },
{ where: { id: result.id } }
);
res.send({messageSent: true});
});
Here is the function definition. Right now I am just returning 1.
In real world the URL returns a code.
async function sendSMS(attendence){
//console.log(target);
setTimeout(function(){
let message = `Respected Parent, your son/daughter ${attendence.student.name} is absent on ${attendence.date}`;
let messageURL = encodeURI(message);
let api = 'SOME VALUE';
let phone = attendence.student.fphone.substring(1, 11);
let target = `http://BASE_URL/api.php?key=${api}&receiver=92${phone}&sender=DigitalPGS&msgdata=${messageURL}`;
return 1;
}, 2000);
}
You should return promise from sendSMS. Resolve promise in setTimeout callback function.
function sendSMS(attendence){
//console.log(target);
return new Promise((resolve, reject) => {
setTimeout(function(){
let message = `Respected Parent, your son/daughter ${attendence.student.name} is absent on ${attendence.date}`;
let messageURL = encodeURI(message);
let api = 'SOME VALUE';
let phone = attendence.student.fphone.substring(1, 11);
let target = `http://BASE_URL/api.php?key=${api}&receiver=92${phone}&sender=DigitalPGS&msgdata=${messageURL}`;
resolve(1);
}, 2000);
});
}
You should have sendSMS return a promise, and await that:
exec();
async function exec()
{
var records = [1,2,3];
for(var i=0;i<records.length;i++)
{
var messageLogId = await sendSMS(records[i]);
console.log("Result received from resolve", messageLogId);
}
}
function sendSMS(record)
{
// simulate an async method:
return new Promise(function(resolve, reject) {
setTimeout(function() {
console.log("Send sms for record", record);
resolve(1);
}, 1000);
});
}
Note that the setTimeout here is just to demonstrate an asynchronous action. In the real world your sendSMS function will no doubt call an API, which will itself be asynchronous - just return the promise from that (or, wrap the call in a promise if the API client doesn't return one).
First, make your function Promisify. Then chunk your function and call that function in the for loop and handle with Promise.all().
const manyPromises = [];
for (const attendence of result.attendences) {
manyPromises.push(sendSmsAndUpdateStatus(attendence));
}
// Execution wait until all promises fulfilled/rejected
const result = await Promise.all(manyPromises);
const sendSmsAndUpdateStatus = async (attendence) => {
try {
const messageLogId = await sendSMS(attendence);
const updateObj = { smsLogId: messageLogId };
const condition = { where: { id: attendence.id } };
const result = await Attendence.update(updateObj, condition);
return { result, messageLogId };
} catch (err) {
logger.error(err);
throw err;
}
};
const sendSMS = (attendence) => {
return new Promise((resolve) => {
setTimeout(() => {
const message = `Respected Parent, your son/daughter ${attendence.student.name} is absent on ${attendence.date}`;
const messageURL = encodeURI(message);
const api = 'SOME VALUE';
const phone = attendence.student.fphone.substring(1, 11);
const target = `http://BASE_URL/api.php?key=${api}&receiver=92${phone}&sender=DigitalPGS&msgdata=${messageURL}`;
return resolve(1);
}, 2000);
});
};
Summary make sure your function sendSMS will return Promise, afterwards you can handle it with async/await or .then().catch() approaches.

Returning promise data to the calling function

let func1 = function() {
return new Promise((resolve,reject) => {
let someVal = 5;
if (condition) {
resolve(someVal);
}
else {
reject('error occured');
}
});
}
let callingFunction = function() {
func1().then((res) => {
console.log("result",res); /* want to return res to the callingFunction */
return res; /* doesn't work as it returns to the .then not to the callingFunction I guess. */
});
}
let finalData = callingFunction();
Is it feasible to send the result from .then block of promise to callingFunction so that I get result in finalData?
let callingFunction = function() {
return func1().then((res) => {
console.log("result",res)
return res
})
}
callingFunction().then((res) => {
let finalData = res
})
The thing is that promise is an asynchronous operation, hence let finalData = callingFunction(); evaluates to undefined. If you'd like to use promise's result in callingFunction(), just pass res as an argument to it like this:
let func1 = function() {
return new Promise((resolve,reject) => {
let someVal = 5;
if (condition) {
resolve(someVal);
}
else {
reject('error occured');
}
});
}
func1().then((res) => {
console.log("result",res); /* want to return res to the callingFunction */
callingFunction(res);
});

Why is my async function not working? I just want it to console.log the results of the mongodb query? [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 5 years ago.
I keep getting Promise { < pending > } on the console.log, I am not too experienced at all with Async functions. (Using JavaScript, Node, Mongodb)
function resolveAfter1() {
return new Promise(resolve => {
var scoresFromDb = db.account.find({}, { username: 1, score: 1 }).toArray(function(err, result) {
if (err) throw err;
// return result;
})
setTimeout(() => {
resolve('resolved');
}, 1000);
});
}
async function asyncCall() {
var result = await resolveAfter1();
}
asyncCall();
console.log(asyncCall());
If you call async function from non async context, it's same as using a promise.
IE. this:
async function something() {return 0;}
var result = something();
is almost the same as this:
function something() {
return new Promise((resolve, reject)=>{resolve(0);});
}
var result = something();
In both cases, result will be a Promise, you can try it in console.
This means, that if you want to get the result, you need to do it from async function:
async function asyncCall() {
var result = await resolveAfter1();
console.log(result);
}
To access async result from since context, you still need to go with good 'ol .then and .catch:
resolveAfter1()
.then((result)=>{console.log(result);})
.catch((error)=>{console.log(error);})
Additionally, you should NOT throw in promise, that's what reject is for:
function resolveAfter1() {
return new Promise((resolve, reject) => {
var scoresFromDb = db.account.find({}, { username: 1, score: 1 }).toArray(function(err, result) {
if (err)
reject(err);
else
resolve(result);
});
});
}
function resolveAfter1() {
return new Promise(resolve => {
var scoresFromDb = db.account.find({}, { username: 1, score: 1 }).toArray(function(err, result) {
if (err) throw err;
// return result;
})
setTimeout(() => {
resolve('resolved');
}, 1000);
});
}
async function asyncCall() {
var result = await resolveAfter1();
console.log(result); // here's your result
return result;
}
asyncCall().then(result => console.log(result));
// console.log(asyncCall());

Categories

Resources