Reputation: 1203
I was trying to understand a little bit more about promises and async programming. I was trying to make an async for loop (yeah, I know there are lots of libs to accomplish this, but they don't teach me how things work) using promises.
Let's say I want to iterate an array, and apply a function to one element "per tick" while I do some other stuff. So I made this "async for-loop-like" function:
function asyncFor_(elements, worker, index) {
return new Promise((resolve, reject) => {
process.nextTick(()=>{
if (index < elements.length) {
try {
worker(elements[index])
resolve(asyncFor_(elements, worker, index+1))
} catch(e) {
reject()
}
} else {
resolve()
}
})
})
}
And test it with this:
function logEnd() {
console.log('End')
}
function logErr(e) {
console.log(e) //Received
console.log('I dont like 3. GTFO.')
}
function logItem(item) {
if (item === 3) {
throw Error('3? GTFO.')
}
console.log(item)
}
console.log('Begin')
asyncFor_([1,2,3,4,5], logItem, 0)
.then(logEnd)
.catch(logErr)
asyncFor_([6,7,8,9], logItem, 0)
.then(logEnd)
.catch(logErr)
console.log('Displayed after begin and before the rest')
The output is:
Begin
1
6
2
7
8
I don't like 3. GTFO
9
End (End from the second asyncFor_ call)
I think this is working fine. But at the same time I'm having doubts. Maybe I am misinterpreting the results. Did I miss something? Is this "asynchrony" an illusion or is it really async?
Upvotes: 1
Views: 101
Reputation: 664206
Yes, it is fine, and yes, it is really asynchronous (as also evidenced by your output log from the two concurrent loops).
However it looks a bit like the Promise
constructor antipattern, and by avoiding that you can greatly simplify your code:
function nextTick() {
return new Promise(resolve => {
process.nextTick(resolve);
});
}
function asyncFor_(elements, worker, index) {
return nextTick().then(() => {
if (index < elements.length) {
worker(elements[index]);
return asyncFor_(elements, worker, index+1);
}
});
}
Putting your code in then
callbacks, you've got the try-catch for free. Always promisify at the lowest possible level! :-)
Upvotes: 1