Redux Saga中如何为yield put()创建定时执行循环?
解决Redux Saga中定时调用
yield put的问题 嘿,这个坑我之前踩过!直接用原生setTimeout确实行不通——因为yield只能在生成器函数的上下文里被Redux Saga的运行时处理,普通定时器函数里的yield根本不会被Saga识别,改成生成器也没用,因为没人去驱动这个生成器迭代。
Redux Saga本身提供了专门处理异步延迟的工具,推荐两种靠谱的实现方式:
方式一:用delay+无限循环(最常用)
Saga自带的delay效果是封装好的异步延迟,它返回一个Promise,能被yield正确处理,而且Saga会自动管理定时器的生命周期(比如取消Saga时自动清理定时器,避免内存泄漏)。
步骤如下:
- 先导入
delay:
import { delay } from 'redux-saga/effects';
- 修改你的
setLoop生成器:
function* setLoop() { // 无限循环,直到Saga被取消(比如takeLatest触发新实例) while (true) { // 触发action yield put({ type: ANOTHER_WATCHER }); // 等待5秒 yield delay(5000); } }
如果需要先等待5秒再执行第一次,把delay放在put前面就行:
function* setLoop() { while (true) { yield delay(5000); yield put({ type: ANOTHER_WATCHER }); } }
方式二:带取消控制的定时任务
如果需要中途停止定时(比如用户点击“停止刷新”按钮),可以用race效果结合take来监听取消动作:
- 导入需要的效果:
import { delay, take, race, call } from 'redux-saga/effects';
- 修改
setLoop:
// 先定义一个取消action的类型,比如 const CANCEL_LOOP = 'CANCEL_LOOP'; function* setLoop() { while (true) { // 同时监听两个任务:定时触发action,或者取消信号 const { cancel } = yield race({ tick: call(function* () { yield put({ type: ANOTHER_WATCHER }); yield delay(5000); }), cancel: take(CANCEL_LOOP), }); // 如果收到取消信号,退出循环 if (cancel) break; } }
之后只要在需要停止的时候dispatch({ type: CANCEL_LOOP }),定时任务就会终止。
为什么你的原写法不行?
你之前尝试的setTimeout里的函数是普通函数,不在Saga生成器的执行上下文里,yield put(...)不会被Saga的运行时处理——Saga需要通过yield来接管异步流程,原生定时器跳出了这个流程,自然无法生效。
内容的提问来源于stack exchange,提问作者David
相关产品推荐
相关产品推荐

