Skip to content

Instantly share code, notes, and snippets.

@twolfson
Last active October 10, 2020 01:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save twolfson/8a283fda713a9ae6597748900a05008c to your computer and use it in GitHub Desktop.
Save twolfson/8a283fda713a9ae6597748900a05008c to your computer and use it in GitHub Desktop.
Exploration of async/await blocking
node_modules/

gist-async-await-blocking-explore

Exploration of async/await blocking

We've been curious how much async/await blocks other actions in Node.js so exploring it

Summarized conclusion:

  • await only blocks the local function, just as nesting all code inside a callback blocks
    • Context/call stack is maintained so nothing to worry about
  • Demos include express so we can 100% verify it doesn't block requests
// Behavior:
// Timeout reached
// End of main
// Explanation:
// Our function halts execution of the rest of the function until the timeout is resolved
// Define our main function
async function main() {
await new Promise((resolve) => {
setTimeout(() => {
console.log('Timeout reached');
resolve();
}, 1e3);
});
console.log('End of main');
}
// Run our main function
main();
// Behavior:
// Submitted 5x requests in parallel
// $ curl http://localhost:3000/ &
// Saw all responses way quicker than with 5s delays
// Verifying `await` works just fine in `express
// $ node express.js
// App listening at http://localhost:3000/
// Timeout reached 1602293925326
// Timeout reached 1602293925920
// Timeout reached 1602293926345
// Timeout reached 1602293926752
// Timeout reached 1602293927150
// Timeout reached 1602293927597
// Load in our dependencies
const express = require('express');
// Build out our app
let app = express();
app.get('/', async function (req, res) {
await new Promise((resolve) => {
setTimeout(() => {
console.log('Timeout reached', Date.now());
resolve();
}, 5e3);
});
res.end('Hello world!');
});
// Start our listener inside of a `main()` function
function main() {
app.listen(3000);
console.log('App listening at http://localhost:3000/');
}
main();
// Behavior:
// Start: 1602292970255 -- 0255ms
// End of main
// Timeout 2 reached 1602292971263 -- 1263ms (so 1s)
// End of timeout 2
// Timeout 1 reached 1602292973265 -- 3265ms (so 3s)
// End of timeout 1
// Command runtime: 3s
// Explanation:
// Each function operates in a callback esque fashion
// due to using generators under the hood
// So `timeout1` runs, hits into `await` and that pauses its execution in the event loop until the `yield` runs
// but that doesn't stop other invocations
// Just as `setTimeout()` doesn't block the event loop
// It persists the context for a later invocation
// Define our nested awaiting functions
async function timeout1() {
await new Promise((resolve) => {
setTimeout(() => {
console.log('Timeout 1 reached', Date.now());
resolve();
}, 3e3);
});
console.log('End of timeout 1');
}
async function timeout2() {
await new Promise((resolve) => {
setTimeout(() => {
console.log('Timeout 2 reached', Date.now());
resolve();
}, 1e3);
});
console.log('End of timeout 2');
}
// Define our main function
async function main() {
console.log('Start:', Date.now());
timeout1();
timeout2();
console.log('End of main');
}
// Run our main function
main();
{
"name": "gist-async-await-blocking-explore",
"version": "1.0.0",
"description": "Exploration of async/await blocking",
"main": "basic-await.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+ssh://git@gist.github.com/8a283fda713a9ae6597748900a05008c.git"
},
"author": "Todd Wolfson <todd@twolfson.com> (http://twolfson.com/)",
"license": "Unlicense",
"bugs": {
"url": "https://gist.github.com/8a283fda713a9ae6597748900a05008c"
},
"homepage": "https://gist.github.com/8a283fda713a9ae6597748900a05008c",
"dependencies": {
"express": "~4.17.1"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment