Say we have a loop.js
file:
longLoop().then(res => console.log('loop result processing started'))
console.log('read file started')
require('fs').readFile(__filename, () => console.log('file processing started'))
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) // arbitrary computation heavy operation
if (i % 1e5 === 0) await null /* solution: await new Promise(resolve => setImmediate(resolve)) */
}
console.log('loop finished')
return res
}
Which if ran (node loop.js
) outputs:
loop started
read file started
loop finished
loop result processing started
timer fires
file processing started
How can this code be rewritten to read and process file while the loop is running in the background?
My solution
What I came up with is this:
longLoop().then(res => console.log('loop result processing started'))
console.log('read file started')
require('fs').readFile(__filename, () => console.log('file processing started'))
setTimeout(() => console.log('timer fires'), 500)
async function longLoop () {
let res = 0
let from = 0
let step = 1e5
let numIterations = 1e7
function doIterations() {
//console.log(from)
return new Promise(resolve => {
setImmediate(() => { // or setTimeout
for (let i = from; (i < from + step) && (i < numIterations); i++) {
res += Math.sin(i)
}
resolve()
})
})
}
console.log('loop started')
while (from < numIterations) {
await doIterations()
from += step
}
console.log('loop finished')
return res
}
Which indeed logs:
loop started
read file started
file processing started
timer fires
loop finished
loop result processing started
Is there a simpler, more concise way to do that? What are the drawbacks of my solution?