Цепные обещания возвращаются из функции генератора - PullRequest
1 голос
/ 23 февраля 2020

Я хочу связать обещания, возвращаемые функцией генератора.

Я ожидаю, что это напечатает:

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

Но это печатает:

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

Что я делаю не так?

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...')

1 Ответ

2 голосов
/ 23 февраля 2020

Дело в том, что ваш console.log отставал на 1 элемент. Итак, ваши итерации были такими:

  1. Исходное значение разрешается
  2. Журналы «Начальное значение», 10 мс разрешается
  3. Журналы «10 мс», 20 мс разрешается
  4. Last then, получает «20 мс» результат, но не регистрирует его, вместо этого регистрирует «готово»

Вы можете увидеть это в следующем примере, который выполнил часть, записывает «20 мс» :

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...')

Но подождите, не хотите ли вы действительно wait последовательно для 10 мс, а затем для 20 мс, верно? Потому что ваша текущая версия этого не делает. Он просто запускает их параллельно, поэтому, вероятно, вы должны сделать это следующим образом:

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...')

Надеюсь, это поможет:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...