Deep in Redux Saga Middleware
# 1. Flow
# 1.1 Register Saga Listeners
- 注册SagaFn监听函数, 并将其注入到Saga Channel中
- 利用闭包的方式将ReduxStore注入到SagaFn内
# 1.2 Subscribe Action
- 支持Action拦截
- 使用channel监听Action
# 1.3 Run Saga Effect
- 根据Generator返回类型不同而做不同处理
# 2. Core API
# fork
fork
--->proc
---> Next State --->promise
Non-Block模式,单独开启一个Task去完成任务
# take
& takeEvery
Take
--->runTakeEffect
--->cb(input)
Block模式,阻塞执行Action任务
TakeEvery
--->Take
--->Fork
--->fsmIterator
(opens new window) Non-Block模式,非阻塞执行每一次请求,并返回Iterator迭代器类型
# call
创建一个 Effect 描述信息,用来命令 middleware 以参数 args 调用函数 fn 。
fn: Function - 一个 Generator 函数, 也可以是一个返回 Promise 或任意其它值的普通函数。
args: Array
# put
& putResolve
put
: 创建一个 Effect 描述信息,用来命令 middleware 向 Store 发起一个 action。 这个 effect 是非阻塞型的,并且所有向下游抛出的错误(例如在 reducer 中),都不会冒泡回到 saga 当中。
putResovle(put.resovle)
: 类似 put,但 effect 是阻塞型的(如果从 dispatch 返回了 promise,它将会等待其结果),并且会从下游冒泡错误。put的Action是AsyncAction
# all
与 all([...effects]) 相同,但就像 race(effects) 那样,传入的是一个带有 label 的 effect 的字典对象。 effects: Object - 一个 {label: effect, ...} 形式的字典对象
注意事项 当并发运行 Effect 时,middleware 将暂停 Generator,直到以下任一情况发生: 所有 Effect 都成功完成:返回一个包含所有 Effect 结果的数组,并恢复 Generator。 在所有 Effect 完成之前,有一个 Effect 被 reject:在 Generator 中抛出 reject 错误。
# apply(context, fn, [args])
call([context, fn], ...args) 的另一种写法。
# cps(fn, ...args)
创建一个 Effect 描述信息,用来命令 middleware 以 Node 风格的函数(Node style function)的方式调用 fn。
# spawn
与 fork(fn, ...args) 相同,但创建的是 被分离的 任务。被分离的任务与其父级任务保持独立,并像顶级任务般工作。父级任务不会在返回之前等待被分离的任务终止,并且所有可能影响父级或被分离的任务的事件都是完全独立的(错误、取消)。
# select
创建一个 Effect,用来命令 middleware 在当前 Store 的 state 上调用指定的选择器(即返回 selector(getState(), ...args) 的结果)。
# flush
创建一个 Effect,用来命令 middleware 从 channel 中冲除所有被缓存的数据。被冲除的数据会返回至 saga,这样便可以在需要的时候再次被利用。
# delay
返回一个 effect 描述信息,用于阻塞执行 ms 毫秒
# throttle(ms, pattern, saga, ...args)
在发起到 Store 并且匹配 pattern 的一个 action 上派生一个 saga。 它在派生一次任务之后,仍然将新传入的 action 接收到底层的 buffer 中,至多保留(最近的)一个。但与此同时,它在 ms 毫秒内将暂停派生新的任务 —— 这也就是它被命名为节流阀(throttle)的原因。其用途,是在处理任务时,无视给定的时长内新传入的 action。
ms: Number - 在 action 开始处理后,无视新 action 的时长;以毫秒为单位。
pattern: String | Array | Function - 有关更多信息,请参见 take(pattern) 的文档
saga: Function - 一个 Generator 函数
args: Array
const throttle = (ms, pattern, task, ...args) => fork(function*() {
const throttleChannel = yield actionChannel(pattern)
while (true) {
const action = yield take(throttleChannel)
yield fork(task, ...args, action)
yield delay(ms)
}
})
2
3
4
5
6
7
8
9
# reference
https://www.jianshu.com/p/715eb01f6a5f