How do I make ES6 generators wait for promises, like in redux-saga?

微笑、不失礼 提交于 2019-12-08 02:14:33

问题


I've read that generators don't wait for promises. How come this is not the case with generators in redux-saga, and how do I make my own generators wait?

For example, this saga:

takeLatest('FETCH_USER_REQUESTED', function*() {
  const fetchPromise = yield put(fetchUser());
  const user = yield fetchPromise;
  console.log(user)
  yield 1
  console.log(1)
})

will output:

Promise
Object // <= user data fetched asynchronously
1

instead of:

Promise
undefined
1

回答1:


How come this is not the case with generators in redux-saga, and how do I make my own generators wait?

This very popular belief, however generators in itself have no relation to Promises or asynchronous functions. Generators is just about make interruptible function with delegating some resources and responsibility to upper level function.

In case of redux-saga, there is two parts: independent saga runner process and scheduler (https://github.com/redux-saga/redux-saga/blob/master/src/internal/runSaga.js) , which is launched by sagaMiddleware.run() command, and effects reactions, which delegates actions into main saga process.

So, simplest process manager in ES6, which emulates redux-saga behavior, will be like that (very simplified):

const ProcessManager = (() => {
let context = new WeakMap();
function PM(rootSaga, lastValue) {
    if(!context.has(rootSaga)) {
        context.set(rootSaga, rootSaga())
    }
    const iterator = context.get(rootSaga);
    const { done, value } = iterator.next(lastValue);
    if(done) {
        context.delete(rootSaga)
        return;
    }
    if(Promise.resolve(value) === value) {
        value.then((asyncValue) => PM(rootSaga, asyncValue))
    } else {
        PM(rootSaga, value)
    }
}
return PM;
})()

const rootSaga = function* () {
    yield new Promise(resolve => setTimeout(resolve, 500));
    console.log('This will be printed after 500 ms from start');
    yield new Promise(resolve => setTimeout(resolve, 500));
    console.log('This will be printed after 1000 ms from start');
}

ProcessManager(rootSaga);


来源:https://stackoverflow.com/questions/47298855/how-do-i-make-es6-generators-wait-for-promises-like-in-redux-saga

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!