何时在redux-saga中使用yield*和yield?

7
我想从一个saga中调用另一个saga。
当然,saga是一个生成函数,并且是异步的。
我应该使用yield *还是始终使用yield
function* mySaga({ payload: { id, name } }) {
    yield myOtherAsyncSaga(); // when to use yield *?
}

3
你所写的 mySaga() 生成器将只返回另一个生成器的一个结果,然后就结束了。yield * 的目的是有效地委托给另一个生成器,并在该生成器完成之前继续返回所有其结果。委托生成器可以在此之前和之后产生自己的值。 - Pointy
如果生成器只返回单个结果,那么 yield 的行为与 yield * 是相同的吗? - Ben Aston
1
那是我的理解,没错;通过几个微不足道的测试函数来实验验证这一点应该很容易。 - Pointy
1
这在很大程度上取决于生成器的使用方式。如果消费者可以递归处理生成的生成器对象,那么这可能根本没有任何区别。 - Bergi
1
通常情况下,在Redux中,yieldyield*是相同的,因为yield会将迭代器输出,而Redux的魔法会使其正常工作,就像您已经输出了一个Promise一样。 yield*只是意味着您自己处理迭代器,而yield则让Redux为您处理它。 - geon
2个回答

9

这个saga是一个生成器函数,是异步的。
我应该使用yield *还是总是使用yield?

完全回答这个问题,首先需要了解saga、中间件、进程管理器和生成器函数的工作原理。实际上,redux-saga实现了两个方面:用于redux store的中间件,拦截并注入自定义操作,以及async process manager,它有自己的tick回调域,并帮助执行异步操作。

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

因此,redux-saga 内部希望客户端 saga 只是 迭代器,它返回适当的效果并可能在闭包激活上下文中存储一些信息 - 对于类似 while(true) 的 saga 进程。因此,在 redux-saga 中没有必须使用 yield * 的用例,因为 yield * 只是将后续迭代器重新委派给上层。

0

简而言之:在 TS 中为了性能和正确的类型解析,始终使用 yield*

如果你在 JS 领域中,yield 会给中间件一个生成器,中间件将自动迭代它。如果你使用 yield*,则会迭代生成器并将所有项都传递给中间件。 在这种情况下没有太大的区别,除了命中中间件会变慢。

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

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接