I have a builder for long running async operations, and I need every one of those operation to run blocking, there should be only single task running at any moment.
In the code example, I want test
to wait until all of it's internal awaits are resolved and only then resolve test
function itself, allowing the code to continue with the next task.
;(async () => {
const after = (time) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
}, time)
})
}
const test = async (item) => {
console.log("running item", item)
await after(100)
console.log("running step 1 item", item)
await after(100)
console.log("running step 2 item", item)
await after(100)
console.log("running step 3 item", item)
await after(100)
console.log("running step 4 item", item)
}
console.log("running")
const promises = [1,2,3,4,5].map((item) => {
return () => {
test(item)
}
})
for (const promise of promises) {
console.log('running promise', promise)
await promise()
}
})()
At the moment, this code gives me an exception UnhandledPromiseRejectionWarning: TypeError: promise is not a function
and also runs all test functions kind of in parallel, when every await
call allows another test
task to be run. Which is according to specifications, but not what I need.
Here is the output at the moment, showing that execution iterates over items, while I want item 1
to be fully processed before item 2
running
running item 1
running item 2
running item 3
running item 4
running item 5
running step 1 item 1
running step 1 item 2
running step 1 item 3
running step 1 item 4
running step 1 item 5
running step 2 item 1
running step 2 item 2
running step 2 item 3
running step 2 item 4
running step 2 item 5
running step 3 item 1
running step 3 item 2
running step 3 item 3
running step 3 item 4
running step 3 item 5
running step 4 item 1
running step 4 item 2
running step 4 item 3
running step 4 item 4
running step 4 item 5
SOLUTION: The key is not to create all promises but rather wait for each one to finish before creating the next one. Code, that works:
;(async () => {
const after = (time) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
}, time)
})
}
const test = async (item) => {
console.log("running item", item)
await after(100)
console.log("running step 1 item", item)
await after(100)
console.log("running step 2 item", item)
await after(100)
console.log("running step 3 item", item)
await after(100)
console.log("running step 4 item", item)
}
console.log("running")
const promises = [1, 2, 3, 4, 5].map((item) => {
return async () => {
await test(item)
}
})
for (const promise of promises) {
await promise()
}
})()