The reason the first version of your code blocks further processing is because await receives an immediately resolving promise (a null value ends with a promise, as if you were doing await Promise.resolve(null) ). This means that the code after await resume during the current "task": it simply pushes the microtask into the task queue, which will be consumed as part of the same task. All other asynchronous things that you expect are waiting in the task queue, not in the microtask queue.
This applies to setTimeout as well as to readFile . Their callbacks are expected in the task queue and, as a result, will not receive priority over the mircrotasks generated by await s.
So, you need a way to make await put something in the task queue, not the microtask queue. This can be done by giving him a promise that will not be immediately resolved, but will be resolved only after the current task.
You can enter this delay using .... setTimeout :
const slowResolve = val => new Promise(resolve => setTimeout(resolve.bind(null, val), 0));
You would call this function with await . Here is a snippet that uses image loading instead of file loading, but the principle is the same:
const slowResolve = val => new Promise(resolve => setTimeout(resolve.bind(null, val), 0)); longLoop().then(res => console.log('loop result processing started')) console.log('read file started') fs.onload = () => console.log('file processing started'); fs.src = "https://images.pexels.com/photos/34950/pexels-photo.jpg?h=350&auto=compress&cs=tinysrgb"; setTimeout(() => console.log('timer fires'), 500) async function longLoop () { console.log('loop started') let res = 0 for (let i = 0; i < 1e7; i++) { res += Math.sin(i)
<img id="fs" src="">
source share