takeEvery 和 takeLatest。为什么?什么时候使用?同时使用?

akh*_*hil 11 reactjs redux redux-saga

我不清楚何时使用takeEvery何时使用takeLatest?在 redux-saga 中。

通过阅读官方文档,我得到了一个基本的区别。但是在takeEvery中创建并发操作有 什么用(例如,用户以快速的速度连续 2 次点击加载用户按钮,第二次点击将调度 USER_REQUESTED 而第一个触发的 fetchUser 尚未终止)

import { takeEvery } from `redux-saga/effects`

function* fetchUser(action) {
  ...
}

function* watchFetchUser() {
  yield takeEvery('USER_REQUESTED', fetchUser)
}
Run Code Online (Sandbox Code Playgroud)

任何人都可以请解释。因为我对 redux-saga 完全陌生。

提前致谢。

iLu*_*gix 15

尽管@Martin Kadlec 的可靠答案涵盖了这个问题,但我想详细说明takeEverytakeLatest的细节和差异以及何时可能使用它们,以便您可以推导出它们的可能用例。

域名注册地址:

当需要所有先前任务的返回时,您可以使用takeEvery。例如,从气象站获取一定时期内的温度和湿度数据以存储在数据库中并显示为图表 - 在这种情况下,所有以前的传奇及其返回值都是相互关联的,而不仅仅是最新的

如果 iE 内部/外部实例或接口的用户可以触发多个连续动作,并且只需要最后一个值的结论,则可以使用takeLatest。一个很好的例子是快速调用经纪人 API 以获得股票价值的实时行情,其中只有最新/最近的价值是感兴趣的

详细的:

takeEverytakeLatest视为 redux-saga 低级 API 之上的辅助函数,它们包装内部操作,例如在将特定操作分派到 Store 时生成任务。调用它们会在分派到与模式匹配的 Store 的每个动作上产生一个传奇。

取每:

最常见的takeEvery函数在行为和方法上与redux-thunk非常相似。它基本上是yield take模式或通道和yield fork.

关于takeEvery的线索是它允许fetchSomeThing同时/同时启动定义的操作/任务的多个实例(例如在下面的示例中)。

takeLatest不同,您可以fetchSomeThing在一个或多个先前的实例fetchSomeThing尚未完成/终止时开始一项新任务,因此仍处于挂起状态。请记住,不能保证任务将按照它们开始的相同顺序终止/完成。要处理无序响应,您可以使用takeLatest

来自官方文档

takeEvery(pattern, saga, ...args)

在分派到与模式匹配的 Store 的每个动作上产生一个 saga。

  • pattern: 字符串 | 数组 | 功能
  • saga: 函数 - 一个生成器函数
  • args: Array - 要传递给启动任务的参数。takeEvery 将传入的动作添加到参数列表中(即动作将是提供给 saga 的最后一个参数)

您还可以将通道作为参数而不是模式传递,从而产生与takeEvery(pattern, saga, ...args)相同的行为。

最新:

takeLatest相比之下辅助函数只得到了的响应最新要求的是被解雇,可以被看作是一个包装yield take的图案或通道和一个额外的if语句检查如果lastTask存在(以前的任务仍悬而未决),然后将通过 ayield cancel和后续yield fork将产生当前任务/操作终止。

来自官方文档

takeLatest(pattern, saga, ...args)

只会得到最新请求的响应。

  • pattern: 字符串 | 数组 | 功能
  • saga: 函数 - 一个生成器函数
  • args: Array - 要传递给启动任务的参数。takeLatest 将传入的动作添加到参数列表中(即动作将是提供给 saga 的最后一个参数)

takeEvery类似,您也可以将通道作为参数而不是模式传递。


Mar*_*lec 12

这是您在每个用例中真正需要考虑的事情。

在某些情况下,您可能会使用takeEvery.

  1. 对于非异步的传奇,因此没有理由取消它们。takeLatest在这里也可以工作,但在阅读代码时可能会给出错误的指示,表明有一些东西要取消。

  2. 有时,当每次的动作都以某种方式不同时。例如,假设您有一部电影并且您正在添加带有电影类型的标签。每次触发动作时,您都会获得不同的类型,即使它是相同的动作类型。用户可以比您从服务器获得响应更快地添加流派。但仅仅因为您快速添加了多种类型并不意味着您想停止添加前一种类型的传奇。

  3. 当您对多个不同的项目具有相同的加载操作时的廉价实现。例如,您有电影列表,每个电影都有“加载详细信息”按钮。(让我们忽略这样一个事实,即加载开始后您可能应该隐藏或禁用该按钮)。一部电影的数据总是相同的,但它们之间有所不同。当您单击电影 1 的加载详细信息时,您不想取消电影 2 的数据加载。由于它是电影的动态列表,因此每次动作类型都相同,差异可能类似于id电影在行动中。

    在理想的实现中,您可能应该取消相同电影/id 的先前加载传奇,但这将需要更复杂的代码,因此如果您只做一些简单的应用程序,您可能会决定忽略它并只允许运行相同的传奇电影多次。这就是我称之为“廉价实施”的原因。


Ced*_*iga 10

简而言之,

  • takeEvery允许处理并发操作。例如,用户快速连续单击“加载用户”按钮两次,第二次单击将调度 USER_REQUESTED 操作,而第一次单击触发的 fetchUser 尚未终止。
    takeEvery不处理来自任务的无序响应。无法保证任务将按照启动顺序终止。要处理无序响应,您可以考虑 takeLatest。
  • takeLatest而是在每个分派的 USER_REQUESTED 操作上启动一个新的 fetchUser 任务。由于 takeLatest会取消之前启动的任何待处理任务,因此我们确保如果用户快速触发多个连续的 USER_REQUESTED 操作,我们只会以最新的操作结束

文档: https: //redux-saga.js.org/docs/api/


小智 5

  • takeEvery - 允许同时使用多个 fetchData 对象。在某一特定时刻,我们可以启动一个新的 fetchData 任务,同时仍有一个或多个先前的 fetchData 任务尚未终止。

  • takeLatest - 在任何给定时刻只能有一个 fetchData 任务处于活动状态。这也将是最近开始的工作。如果在先前的任务仍在运行时启动新的 fetchData 作业,则先前的工作将立即终止。