Reputation: 45
I currently have this function here
async function checkEntry(results: any) {
let ind = 0;
for (let i = 0; i < results.length; i++) {
const e = results[i];
await checkStuff(e); // returns void
await checkOtherStuff(e); //returns void
await updateStatus(e); //returns void aswell
ind++;
await sleep(1);
}
}
Now i would imagine that this would execute checkStuff, checkOtherStuff, updateStatus in this order and then go into the next iteration of the for-loop.
Instead it piles up promises of checkStuff and after the loop is done (console logs 10,000 of 10,000) it still gives me results of the first function called for a while.
Why does this function not run in the order I intended it to run? Or rather, why does the await keyword not block the execution of the loop for the time it takes to complete the call?
Edit: Content of the checkStuff function:
async function checkStuff(result: any) {
try {
const req = await https.get(result.url, async (res) => {
if(res.statusCode == 404) console.log(result.url+' returns 404');
});
req.on("error", (e) => {
// console.error(e);
});
} catch (err) {
// console.error(err);
}
}
Upvotes: 2
Views: 354
Reputation: 4975
If you are using the await keyword, you need to use it on a promise.
Currently checkStuff
isn't returning a promise so you might adapt your code to resolve the promise when the callback is executed.
const https = require('https');
function checkStuff(result) {
return new Promise((resolve, reject) => {
const req = https.get(result.url, (res) => {
if (res.statusCode == 404) {
console.log(result.url + ' returns 404');
reject(res);
} else {
resolve(res);
}
});
req.on('error', (e) => {
console.error(e);
reject(e);
});
}).catch((e) => {
console.log(e);
});
}
A callback and a Promise are different.
When a method takes a callback, it says, when I've finished this task, I'll call a function of your choice.
When you use promises, you create a Promise object and return it. It will stay as "Pending" until something inside that promise calls resolve or reject. You can pass a result into resolve or reject like this resolve(data)
.
Now by assigning this promise to a variable inside an async
function, you have unlocked the await
keyword. await
will prevent your code from moving to the next line until the promise is resolved, so this helps you make your code synchronous.
async function main() {
const result = await checkStuff();
/*
Result is now a Promise object in the pending state.
The code will not continue past the previous line
until the result variable changes from pending to resolved.
*/
console.log(result);
}
Upvotes: 2
Reputation: 40842
https.get
does not provide a promise interface and await
does not magically make your code wait for an asynchronous task to finish.
It is synthetic sugar to make it easier to work with Promises and requires a Promise to work.
If a function like https.get
does not provide a Promise interface then you need in some way to convert it into a Promise, by e.g. wrapping a new Promise((resolve, reject) => …)
around it.
const req = await new Promise((resolve, reject) => {
https.get(result.url, async (res) => {
if(res.statusCode == 404) console.log(result.url+' returns 404');
resolve()
});
req.on("error", (e) => {
reject(e)
});
})
Upvotes: 1