takeEvery 和 takeLatest。为什么?什么时候使用?同时使用?
takeEvery and takeLatest. Why? When to use? Use simultaneously?
我不清楚什么时候使用 takeEvery 什么时候使用 takeLatest ?在 redux-saga 中。
通过阅读官方文档,我得到了一个基本的区别。但是在 takeEvery 中创建并发操作有什么用(例如,用户快速连续点击 Load User 按钮 2 次,第二次点击将发送 USER_REQUESTED 而第一个触发的 fetchUser 尚未终止)
import { takeEvery } from `redux-saga/effects`
function* fetchUser(action) {
...
}
function* watchFetchUser() {
yield takeEvery('USER_REQUESTED', fetchUser)
}
谁能解释一下。因为我对 redux-saga 完全陌生。
提前致谢。
这是您真正需要根据用例考虑的事情。
在某些情况下您可能会使用 takeEvery
。
对于非异步的传奇,因此没有理由
取消它们。 takeLatest
也可以在这里工作,但它可能会给
阅读代码时的错误指示
取消。
有时每次的操作在某些方面有所不同。例如。
假设您有一部电影,并且要添加类型为
电影。每次触发动作时,您都会获得不同的流派,
即使它是相同的操作类型。用户可以添加流派
比您从服务器获得响应更快。但就因为你
快速添加多种类型并不意味着您想停止传奇
添加上一个。
当您具有相同的加载操作时的廉价实现
多个不同的项目。例如。你有电影列表,每个都有
"load detail" 按钮。 (让我们忽略你应该
加载开始后可能会隐藏或禁用按钮)。这
一部电影的数据始终相同,但它们之间有所不同。
当您单击电影 1 的加载详细信息时,您不想取消
加载电影 2 的数据。因为它是电影的动态列表
动作类型每次都是一样的,区别会是
可能类似于电影中的动作 id
。
在理想的实现中,您应该取消之前的加载传奇
相同的 movie/id,但这将需要更复杂的代码和
所以如果你只做一些简单的应用程序,你可能会决定忽略
那并且只允许 运行 同一部电影的传奇故事多次。
这就是为什么我称它为 "cheap implementation".
虽然@Martin Kadlec 的可靠回答涵盖了这个问题,但我想详细说明 takeEvery 和 takeLatest[=101= 的细节和差异] 以及何时可能使用它们,以便您可以推导出它们的可能 use-cases。
TLDR:
当需要returns之前的所有任务时,您可以使用takeEvery。例如,在一定时期内从气象站获取温度和湿度数据,以将其存储在数据库中并显示为图表 - 在这种情况下,所有以前的传奇及其 return-values 是相互交集的,并且 不仅最新.
如果 i.E.,您可以使用 takeLatest internal/external 实例或接口的用户可以触发多个连续的操作,并且只需要最后一个值的结论。一个很好的例子是快速调用 broker-API 获取 live-ticker 获取 stock-values,其中只有 latest/most 最近的值感兴趣 .
详细:
将 takeEvery 和 takeLatest 视为 redux-saga 的较低级别 API 之上的辅助函数当特定操作被分派到 Store 时,它包装了内部操作,例如生成任务。调用它们会在每个派发到与模式匹配的商店的动作上产生一个传奇。
takeEvery:
最常见的 takeEvery 函数在行为和方法上与 redux-thunk 非常相似。它基本上是模式或通道的 yield take
和 yield fork
.
的包装器
关于takeEvery的线索是它允许启动一个已定义action/task的多个实例(例如下面示例中的fetchSomeThing
)concurrently/simultaniously.
与 takeLatest 不同,您可以在 fetchSomeThing
的一个或多个先前实例尚未 completed/terminated 时开始新的 fetchSomeThing
任务,因此仍然悬而未决。请记住,不能保证任务 terminate/complete 会按照它们开始时的顺序进行。要处理乱序响应,您可以使用 takeLatest.
来自官方docs:
takeEvery(pattern, saga, ...args)
在发送到与模式匹配的 Store 的每个操作上生成一个 saga。
pattern
:字符串 |数组 |函数
saga
: 函数 - 生成器函数
args
:数组 - 要传递给启动任务的参数。 takeEvery 会将传入的动作添加到参数列表中(即动作将是提供给 saga 的最后一个参数)
您还可以传入通道作为参数而不是模式,从而导致与 takeEvery(pattern, saga, ...args).[=28= 相同的行为]
取最新:
相比之下,takeLatest 辅助函数仅获取被触发的 最新请求 的响应,可以看作是对yield take
的 模式或通道 和额外的 if-statement 检查是否存在 lastTask(之前的任务是仍然悬而未决),然后将通过 yield cancel
和随后的 yield fork
终止,这将产生当前的 task/action.
来自官方docs:
takeLatest(pattern, saga, ...args)
只会得到最近触发的请求的响应。
pattern
:字符串 |数组 |函数
saga
: 函数 - 生成器函数
args
:数组 - 要传递给启动任务的参数。 takeLatest 会将传入的动作添加到参数列表中(即动作将是提供给 saga 的最后一个参数)
与 takeEvery 类似,您也可以传入通道作为参数而不是模式。
总结一下,
- takeEvery 允许处理并发操作。例如,用户快速连续点击加载用户按钮 2 次,第二次点击将发送一个 USER_REQUESTED 动作,而第一次点击时 fetchUser 尚未终止。
takeEvery 不处理来自任务的乱序响应。无法保证任务将按照它们开始的相同顺序终止。要处理乱序响应,您可以考虑 takeLatest。
- takeLatest 而不是在每个分派的 USER_REQUESTED 操作上启动一个新的 fetchUser 任务。由于 takeLatest 取消了 之前启动的任何待处理任务,我们确保如果用户快速触发多个连续的 USER_REQUESTED 操作,我们只会以最新的行动结束
takeEvery - 允许同时使用多个 fetchData 对象。
在给定的时刻,我们可以启动一个新的 fetchData 任务
仍然是一个或多个以前的 fetchData 任务
尚未终止。
takeLatest - 在任何给定时刻只能激活一个 fetchData 任务。它
也将是最近开始的工作。如果一个新的
fetchData 作业在上一个任务仍在 运行 时启动,
之前的工作将立即终止
我不清楚什么时候使用 takeEvery 什么时候使用 takeLatest ?在 redux-saga 中。
通过阅读官方文档,我得到了一个基本的区别。但是在 takeEvery 中创建并发操作有什么用(例如,用户快速连续点击 Load User 按钮 2 次,第二次点击将发送 USER_REQUESTED 而第一个触发的 fetchUser 尚未终止)
import { takeEvery } from `redux-saga/effects`
function* fetchUser(action) {
...
}
function* watchFetchUser() {
yield takeEvery('USER_REQUESTED', fetchUser)
}
谁能解释一下。因为我对 redux-saga 完全陌生。
提前致谢。
这是您真正需要根据用例考虑的事情。
在某些情况下您可能会使用 takeEvery
。
对于非异步的传奇,因此没有理由 取消它们。
takeLatest
也可以在这里工作,但它可能会给 阅读代码时的错误指示 取消。有时每次的操作在某些方面有所不同。例如。 假设您有一部电影,并且要添加类型为 电影。每次触发动作时,您都会获得不同的流派, 即使它是相同的操作类型。用户可以添加流派 比您从服务器获得响应更快。但就因为你 快速添加多种类型并不意味着您想停止传奇 添加上一个。
当您具有相同的加载操作时的廉价实现 多个不同的项目。例如。你有电影列表,每个都有 "load detail" 按钮。 (让我们忽略你应该 加载开始后可能会隐藏或禁用按钮)。这 一部电影的数据始终相同,但它们之间有所不同。 当您单击电影 1 的加载详细信息时,您不想取消 加载电影 2 的数据。因为它是电影的动态列表 动作类型每次都是一样的,区别会是 可能类似于电影中的动作
id
。在理想的实现中,您应该取消之前的加载传奇 相同的 movie/id,但这将需要更复杂的代码和 所以如果你只做一些简单的应用程序,你可能会决定忽略 那并且只允许 运行 同一部电影的传奇故事多次。 这就是为什么我称它为 "cheap implementation".
虽然@Martin Kadlec 的可靠回答涵盖了这个问题,但我想详细说明 takeEvery 和 takeLatest[=101= 的细节和差异] 以及何时可能使用它们,以便您可以推导出它们的可能 use-cases。
TLDR:
当需要returns之前的所有任务时,您可以使用takeEvery。例如,在一定时期内从气象站获取温度和湿度数据,以将其存储在数据库中并显示为图表 - 在这种情况下,所有以前的传奇及其 return-values 是相互交集的,并且 不仅最新.
如果 i.E.,您可以使用 takeLatest internal/external 实例或接口的用户可以触发多个连续的操作,并且只需要最后一个值的结论。一个很好的例子是快速调用 broker-API 获取 live-ticker 获取 stock-values,其中只有 latest/most 最近的值感兴趣 .
详细:
将 takeEvery 和 takeLatest 视为 redux-saga 的较低级别 API 之上的辅助函数当特定操作被分派到 Store 时,它包装了内部操作,例如生成任务。调用它们会在每个派发到与模式匹配的商店的动作上产生一个传奇。
takeEvery:
最常见的 takeEvery 函数在行为和方法上与 redux-thunk 非常相似。它基本上是模式或通道的 yield take
和 yield fork
.
关于takeEvery的线索是它允许启动一个已定义action/task的多个实例(例如下面示例中的fetchSomeThing
)concurrently/simultaniously.
与 takeLatest 不同,您可以在 fetchSomeThing
的一个或多个先前实例尚未 completed/terminated 时开始新的 fetchSomeThing
任务,因此仍然悬而未决。请记住,不能保证任务 terminate/complete 会按照它们开始时的顺序进行。要处理乱序响应,您可以使用 takeLatest.
来自官方docs:
takeEvery(pattern, saga, ...args)
在发送到与模式匹配的 Store 的每个操作上生成一个 saga。
pattern
:字符串 |数组 |函数saga
: 函数 - 生成器函数args
:数组 - 要传递给启动任务的参数。 takeEvery 会将传入的动作添加到参数列表中(即动作将是提供给 saga 的最后一个参数)
您还可以传入通道作为参数而不是模式,从而导致与 takeEvery(pattern, saga, ...args).[=28= 相同的行为]
取最新:
相比之下,takeLatest 辅助函数仅获取被触发的 最新请求 的响应,可以看作是对yield take
的 模式或通道 和额外的 if-statement 检查是否存在 lastTask(之前的任务是仍然悬而未决),然后将通过 yield cancel
和随后的 yield fork
终止,这将产生当前的 task/action.
来自官方docs:
takeLatest(pattern, saga, ...args)
只会得到最近触发的请求的响应。
pattern
:字符串 |数组 |函数saga
: 函数 - 生成器函数args
:数组 - 要传递给启动任务的参数。 takeLatest 会将传入的动作添加到参数列表中(即动作将是提供给 saga 的最后一个参数)
与 takeEvery 类似,您也可以传入通道作为参数而不是模式。
总结一下,
- takeEvery 允许处理并发操作。例如,用户快速连续点击加载用户按钮 2 次,第二次点击将发送一个 USER_REQUESTED 动作,而第一次点击时 fetchUser 尚未终止。
takeEvery 不处理来自任务的乱序响应。无法保证任务将按照它们开始的相同顺序终止。要处理乱序响应,您可以考虑 takeLatest。 - takeLatest 而不是在每个分派的 USER_REQUESTED 操作上启动一个新的 fetchUser 任务。由于 takeLatest 取消了 之前启动的任何待处理任务,我们确保如果用户快速触发多个连续的 USER_REQUESTED 操作,我们只会以最新的行动结束
takeEvery - 允许同时使用多个 fetchData 对象。 在给定的时刻,我们可以启动一个新的 fetchData 任务 仍然是一个或多个以前的 fetchData 任务 尚未终止。
takeLatest - 在任何给定时刻只能激活一个 fetchData 任务。它 也将是最近开始的工作。如果一个新的 fetchData 作业在上一个任务仍在 运行 时启动, 之前的工作将立即终止