1 year ago
#372023
Gandalf
Why does calling setTimeout unblocks the event loop in this example?
The following code is from this medium article
const fastify = require("fastify")({ logger: true });
const crypto = require("crypto");
const randomstring = require("randomstring");
// Declare healthcheck ping-pong
fastify.get("/ping", (_request, reply) => {
reply.send({ data: "pong" });
});
fastify.get("/event-loop-blocking-operation", async (_request, reply) => {
let hash = crypto.createHash("sha256");
const numberOfHasUpdates = 10e6;
for (let iter = 0; iter < numberOfHasUpdates; iter++) {
hash.update(randomstring.generate());
}
reply.send({ data: "Finished doing long task" });
});
fastify.get("/event-loop-nonblocking-operation", async (_request, reply) => {
const hash = crypto.createHash("sha256");
const numberOfHasUpdates = 10e6;
const breathSpace = async (delayInS) =>
new Promise((resolve, reject) => {
setTimeout(() => resolve(), delayInS * 1000);
});
for (let iter = 0; iter < numberOfHasUpdates; iter++) {
const hashed = hash.update(randomstring.generate());
await breathSpace(0);
}
reply.send({ data: "Finished long process" });
});
// Run the server!
const port = 3000;
fastify.listen(port, (err, address) => {
if (err) {
fastify.log.error(err);
process.exit(1);
}
fastify.log.info(`server listening on ${address}`);
});
case 1
#in Terminal 1
$ node blocking_event_loop.js
#in Terminal 2
#calls 127.0.0.1:3000/ping every one second
#keeps printing {data: "pong"} in terminal
$ while true; do date; curl 127.0.0.1:3000/ping; sleep 1; echo \n; done;
#in Terminal 3
#blocks the event loop
$ date && curl 127.0.0.1:3000/event-loop-blocking-operation && date
After calling the last command, the event loop gets blocked and Terminal 2 stops printing.
case 2
#in Terminal 1
$ node blocking_event_loop.js
#in Terminal 2
#calls 127.0.0.1:3000/ping every one second
#keeps printing {data: "pong"} in terminal
$ while true; do date; curl 127.0.0.1:3000/ping; sleep 1; echo \n; done;
#in Terminal 3
#does not block the event loop
$ date && curl 127.0.0.1:3000/event-loop-nonblocking-operation && date
In 2nd case, After calling the last command, Terminal 2 keeps printing {data: "pong"}
and the operation defined in the /event-loop-blocking-operation
's route handler keeps doing what it's doing.
How is it that calling await breathSpace(0)
in the loop will run the operation in a non-blocking way?
As far as I know when the /event-loo-nonblocking-operation endpoint is called via curl:
/event-loop-nonblocking-operation
's corresponding route handler is enqueued to theI/O callback queue
which is also known as poll queue- route handler is dequeued from poll queue and pushed to call stack
- route handler's code is run line by line
3.1
hash.update
method is called (on each iteration of for loop) 3.2await breathSpace(0)
is called (on each iteration of for loop) 3.2.1 the (resolve, reject) => setTimeout(() => resolve(), 0) is enqueued to the Timer queue
Now considering event loop not getting blocked, Does this mean, that even though the first iteration of the loop is not done, event loop changes it's phase from poll to timer to handle the setTimeout which resolves the promise? How does it do the for loop without blocking?
javascript
node.js
async-await
event-loop
0 Answers
Your Answer