Created
March 25, 2016 18:44
-
-
Save ghaiklor/9682b79353aade8a1e59 to your computer and use it in GitHub Desktop.
This example shows how you can block event loop in NodeJS
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
// The purpose of this example is to show | |
// how you can block the event loop with JavaScript. | |
// There is 3 routes | |
// / respond with Hello, World text | |
// /block uses JavaScript while for 5 seconds | |
// /non-block uses setTimeout for 5 seconds | |
// Do the following | |
// curl localhost:3000/ | |
// You get Hello, World | |
// curl localhost:3000/block and curl localhost:3000/ at once | |
// your server is blocked now, because of while in JavaScript | |
// JavaScript code is executed in the main thread, where event loop | |
// that's why it blocks, because of while execution | |
// curl localhost:3000/non-block and curl:localhost:3000/ at once | |
// you will get Hello, World and after 5 seconds I am done | |
// in this case you don't block the server | |
// because operation thrown in thread-pool | |
// freeing the main thread for other connections | |
const express = require('express'); | |
const app = express(); | |
app.get('/', (req, res) => res.send('Hello, World')); | |
app.get('/block', (req, res) => { | |
const end = Date.now() + 5000; | |
while (Date.now() < end) { | |
const doSomethingHeavyInJavaScript = 1 + 2 + 3; | |
} | |
res.send('I am done!'); | |
}); | |
app.get('/non-block', (req, res) => { | |
// Imagine that setTimeout is IO operation | |
// setTimeout is a native implementation, not the JS | |
setTimeout(() => res.send('I am done!'), 5000); | |
}); | |
app.listen(3000, () => console.log('app listening on port 3000')); |
It makes sense, thank you @smitparaggua
function unblock() {
return new Promise((resolve) => {
setTimeout(resolve);
});
}
function doHeavyTask() {
console.log('Begin heavy task');
return new Promise((resolve) => {
const end = Date.now() + 30000;
while (Date.now() < end) {
await unblock();
}
log('End heavy task', );
resolve('Done');
});
}
app.get('/non-block', (req, res) => {
console.log('Non-blocked process called');
doHeavyTask().then((result) => {
res.send(result);
});
});
I think your code is just a big mistake, please check the:
http://latentflip.com/loupe/
your call back function in your non-blocking API doesn't run in the backside of your code! when after 5000MS that setTimeout API finished that job and goes to callback queue, event loop catch that callback function and send that to the Stack for executing ! so that callback finally should run into the stack, and in this case, your code's show to non-blocking in stack not in event loop!
Is there a way to tell blocking event from CPU flamechart? Even though a task can be promised, if it's a heavy task, it can still block next event loop right?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@minh-nguyen-hs, Promises doesn't run tasks in a separate thread. This is why event loop will still block. Node handles async tasks by letting go of event loop when waiting (usually while waiting for IO), then picking another task from the available tasks.
In your case, since
doHeavyTask
isn't actually waiting (it's keeping the CPU busy), it blocks the event loop.