如何让 ES6 生成器等待承诺,就像在 redux-saga 中一样?

Posted

技术标签:

【中文标题】如何让 ES6 生成器等待承诺,就像在 redux-saga 中一样?【英文标题】:How do I make ES6 generators wait for promises, like in redux-saga? 【发布时间】:2018-04-28 04:09:28 【问题描述】:

我读过生成器不会等待承诺。为什么redux-saga 中的生成器不是这种情况,如何让我自己的生成器等待?

例如,这个传奇:

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

将输出:

Promise
Object // <= user data fetched asynchronously
1

代替:

Promise
undefined
1

【问题讨论】:

yield 关键字不是等待返回值吗?你能告诉我你在哪里读到的吗? 我在这里读到了:***.com/questions/44083873/… 我错了。这是一个很好的解释。 ***.com/questions/34930735/… 【参考方案1】:

为什么 redux-saga 中的生成器不是这种情况,如何让我自己的生成器等待?

这个非常流行的信念,但是生成器本身与 Promise 或异步函数无关。生成器只是通过将一些资源和责任委托给上层函数来制作可中断的函数。

redux-saga 的情况下,有两部分:独立的saga runner 进程和调度程序(https://github.com/redux-saga/redux-saga/blob/master/src/internal/runSaga.js),由sagaMiddleware.run() 命令启动,以及effects 反应,它将动作委托给主saga 进程。

所以,ES6 中最简单的进程管理器,它模拟redux-saga 行为,将是这样的(非常简化):

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);

【讨论】:

以上是关于如何让 ES6 生成器等待承诺,就像在 redux-saga 中一样?的主要内容,如果未能解决你的问题,请参考以下文章

如何让 React Redux 异步操作返回一个承诺?

javascript - redux thunk 不等待任何承诺

如何键入 Redux thunk 动作创建者以返回承诺

redux thunk - 承诺完成后如何在嵌套数组中调度数据

如何使用 Redux Promise 为我的组件获得已解决的承诺?

如何让控制器等待从角度服务解决的承诺