Run the snippets and look at their durations you'll see that first snippet executes log('Synchronous 2')
before billion loops done
. It spent 0ms, but 2nd snippet using async keyword blocks log('Synchronous 2')
until the loop is finished.
const tick = Date.now();
const log = (v) => console.log(`${v} \n Elapsed: ${Date.now() - tick}ms`);
const notBlocked = () => {
return Promise.resolve().then(() => {
let i = 0;
while(i < 1000000000) { i++; } //runs asynchronically
return '🐷 billion loops done';
})
}
log('🥪 Synchronous 1');
notBlocked().then(log);
log('🥪 Synchronous 2');
The log('Synchronous 2') is blocked
const tick = Date.now();
const log = (v) => console.log(`${v} \n Elapsed: ${Date.now() - tick}ms`);
const notBlocked = async() => {
let i = 0;
while(i < 100000000) { i++; } //runs synchronically and blocks main thread
return '🐷 billion loops done';
}
log('🥪 Synchronous 1');
notBlocked().then(log);
log('🥪 Synchronous 2');
Async functions run synchronously until they hit an await, so if your goal is to use an async function to delay some code as a microtask, you'll need to stick an await in there, even if it's awaiting something useless.
const tick = Date.now();
const log = (v) => console.log(`${v} \n Elapsed: ${Date.now() - tick}ms`);
const notBlocked = async () => {
await undefined; // yield until the microtasks run
let i = 0;
while(i < 1000000000) { i++; }
return '🐷 billion loops done';
}
log('🥪 Synchronous 1');
notBlocked().then(log);
log('🥪 Synchronous 2');