简体   繁体   中英

Chaining promises returned from a generator function

I want to chain the promises returned by a generator function.

I am expecting this to print:

started...
result is: initial value
result is: waited for 10ms
result is: waited for 20ms
done

But it prints:

started...
result is: initial value
undefined
result is: waited for 10ms
done

What am I doing wrong?

 const wait = async(ms) => await new Promise((resolve) => setTimeout((result = `waited for ${ms}ms`)=>resolve(result),ms)) const iterator = { *[Symbol.iterator]() { yield wait(10) yield wait(20) } } function chain(i) { return [...i].reduce((acc,c) => acc.then((result) => (console.log(`result is: ${result}`), c)), Promise.resolve('initial value')) } chain(iterator).then(() => console.log('done')) console.log('started...')

The things is that your console.log was lagging by 1 element. So your iterations were like that:

  1. Initial value resolves
  2. Logs 'Initial value', 10ms resolves
  3. Logs '10ms', 20ms resolves
  4. Last then , gets '20ms' a result but doesn't log it, instead logs 'done'

You could see it in the next sample, that done part logs '20ms':

 const wait = async(ms) => await new Promise((resolve) => setTimeout(resolve,ms, `waited for ${ms}ms`)) const iterator = { *[Symbol.iterator]() { yield wait(10) yield wait(20) } } function chain(i) { return [...i].reduce((acc,c) => acc.then((result) => (console.log(`result is: ${result}`), c)), Promise.resolve('initial value')) } chain(iterator).then((val) => console.log('done', val)) // <~ 20ms logs here console.log('started...')

But wait, would you like to really wait sequentially for 10ms and then for 20ms, right? Because your current version isn't doing this. It just runs them in parallel, so probably you should do it in this way:

 const wait = ms => new Promise((resolve) => setTimeout(resolve,ms, `waited for ${ms}ms`)) const iterator = { *[Symbol.iterator]() { yield wait(500) yield wait(1000) } } async function chain(i) { console.log('init') for (const promise of i) { const result = await promise console.log(`result is: ${result}`) } } chain(iterator).then(() => console.log('done')) console.log('started...')

Hope it helps :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM