I have a running express application which listens for GET requests. Any GET request immediately returns a success response and runs a function asyncForLoop()
which returns a promise which resolves after 5 seconds.
Problem: Even though asyncForLoop()
gets called after res.json()
any upcoming GET request afterwards gets delayed until the promise in asyncForLoop()
gets resolved.
const express = require("express");
const app = express();
app.listen(3005, () => {
console.log(new Date().getTime() " running on port 3005.");
});
app.get("/*", (req, res) => {
myResponse(req, res);
});
function myResponse(req, res) {
console.log(new Date().getTime() " GET request => " req.originalUrl);
res.json({ success: true });
// this function blocks any following request until it is resolved
asyncForLoop().then(res => {
console.log(new Date().getTime() " finished for-loop.");
});
}
function asyncForLoop() {
return new Promise(function(resolve, reject) {
// simulate a long synchronous action using wait() in a for-loop
for (let i=0; i<5; i ) {
console.log(i);
wait(1000);
}
resolve();
});
}
function wait(ms) {
let start = Date.now(),
now = start;
while (now - start < ms) {
now = Date.now();
}
}
You can test the code above by running the script using node
and opening two tabs with the address localhost:3005
in a browser. The first tab will immediately get a response while the second tab loads for 5 seconds.
Question: Why does the promise inside asyncForLoop()
delay upcoming requests? Shouldn't it be handled asynchronously because it's inside a promise? How can I prevent this delayed second request?
Thanks!
CodePudding user response:
JavaScript is single-threaded. A long running loop will block all your code. You can use an asynchronous wait
function:
const express = require("express");
const app = express();
app.get("/*", (req, res) => {
myResponse(req, res);
});
async function myResponse(req, res) {
console.log(new Date().getTime() " GET request => " req.originalUrl);
res.json({ success: true });
await asyncForLoop();
console.log(new Date().getTime() " finished for-loop.");
}
async function asyncForLoop() {
for (let i=0; i<5; i ) {
console.log(i);
await wait(1000);
}
}
function wait(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
app.listen(3005, () => {
console.log(new Date().getTime() " running on port 3005.");
});