我什么时候应该在 redux-saga 中使用 yield* 与 yield?

When should I use yield* vs yield in redux-saga?

我想从传奇中调用另一个传奇。

saga 当然是一个生成器函数,而且是异步的。

我应该使用 yield * 还是应该一直使用 yield

function* mySaga({ payload: { id, name } }) {
    yield myOtherAsyncSaga(); // when to use yield *?
}

The saga is of course a generator function, and is asynchronous.
Should I ever user yield * or should I always use yield?

完整回答一个问题,首先需要理解saga,middlewares,process manager和generator functions一般是如何工作的。事实上 redux-saga 实现了两方面:用于 redux 存储的中间件,它拦截并注入自定义操作,以及 async process manager,它有自己的 tick 回调域并帮助执行异步操作。

接下来,每个客户端实现的 saga 函数就是 effect creator。事实上,客户端 saga 功能是这样实现的,它实际上什么都不做,但效果创建 - calltakeput 等。此外,saga 不是同步或异步的从本质上讲 - 它只是将一些行为委托给 saga 流程管理器,并执行请求的操作 - 例如,等待承诺。
当然,你可以在client saga中手动进行promise/async处理,但是这样的动作会落入saga事件循环中。

因此,redux-saga 内部人员希望客户端传奇只是 an iterator,这 returns 适当的效果并且可能在闭包激活上下文中存储一些信息 - 在 [=15 的情况下=]- 就像 saga 过程。因此,redux-saga 中没有用例,其中 yield * 是强制性的,因为 yield * 只是将后续迭代器重新委托给上层。

TLDR:在 TS

中始终使用 yield* 来提高性能和正确的类型解析

如果你在 JS 领域,yield 给中间件一个生成器,中间件会自动迭代它。如果您使用 yield*,您将迭代生成器并将所有项目生成给中间件。 这种情况下没有太大区别,只是命中中间件比较慢。

使用 TypeScript 时,情况会发生一些变化:yield 意味着生成器的迭代将发生在中间件中,因此我们的类型将不正确。相反,如果我们使用 yield*,迭代将在我们的范围内发生,TS 将能够检测到正确的类型。

有一个小型 TS 库可以更好地说明这一点:https://www.npmjs.com/package/typed-redux-saga