在普通生成器和Redux传奇之间产生承诺的不同行为

时间:2019-01-17 08:36:33

标签: javascript generator es6-promise redux-saga

据我所知,您无法通过yield生成器中的承诺来获得承诺。并且以下测试证明它是正确的。 ret未定义:

function* foo() {
  const ret = yield Promise.resolve(50);
  console.log(`ret is ${ret}`);
}

const fooGen = foo();
fooGen.next();
fooGen.next()

但是我不知道为什么我可以在Redux传奇中获得已解决的Promise值。请参见以下示例(jsfiddle:https://jsfiddle.net/vymgr7de/1/

// Sagas
function* saga() {
  yield call(function*() {
    const ret = yield Promise.resolve(50);
    yield put({type: "*", payload: `ret is ${ret}`});
  });
}

// => ret is 50

Redux传奇扮演什么技巧?

1 个答案:

答案 0 :(得分:2)

为了扩大我的评论,这里是一个执行类似操作的代码示例

function * test() {
    const result = yield new Promise(resolve => setTimeout(() => resolve('foo'), 1000))
    console.log('Result is: ', result)
}

function run(gen) {
    const iter = gen()
    const makeStep = (err, value) => {
        const step = !err ? iter.next(value) : iter.throw(err)
        if (step.done) return
        const p = step.value instanceof Promise ? step.value : Promise.resolve(step.value)
        p.then(val => makeStep(null, val), err => makeStep(err))
    }
    makeStep()
}

run(test)

如您所见,我正在生成器上进行迭代,每当我找到一个承诺时,我都会等到它被解决后再将解决的值传递给iter.next(value),如果发现其他任何内容,我都会将其转换为解决的Promise因此yield表达式可以立即解析为它产生的任何结果。

当然,redux-saga不仅要寻找承诺,还要寻找各种效果,每种效果都有自己定义的功能。