Channels
Redux-Saga 中的 Channel 通常用于对 Action 进行排序和与外部事件源进行通信。
使用 actionChannel(pattern)
可以创建一个容纳匹配 pattern
的 Action 的队列。这个队列可以缓存所有未执行的 Action。以下是一个缓存所有 Action 并按照顺序处理的示例。
function* watchRequest() {
// 创建一个队列
const requestQueue = yield actionChannel('RQUEST');
while (true) {
// 从队列中取出一个 Action
const { payload } = yield take(requestQueue);
// 调用 Action 对应的处理方法,并阻塞当前 Saga
yield call(handleRequest, payload);
}
}
默认情况下 actionChannel
会无限制的缓存所有传入的 Action,但是可以通过提供第二个参数来为 Channel 指定一个缓存。Redux-Sage 提供了以下这些内置的缓存实现可供使用。
buffers.none()
,不缓存,未被处理的 Action 将会被丢弃。buffers.fixed(limit)
,容量为limit
的缓存,溢出时将会报错。buffers.expanding(initialSize)
,与fixed
相似,但溢出时会动态扩展。buffers.dropping(limit)
,容量为limit
的缓存,溢出时会丢弃最新的 Action。buffers.sliding(limit)
,容量为limit
的缓存,溢出时会丢弃最古老的 Action。
与 actionChannel 类似,eventChannel
可以为外来事件源创建一个 Channel。eventChannel
接受一个函数作为参数,即 subscriber
,其主要任务是初始化外部事件来源,eventChannel
会为 subscriber
提供一个 emitter
来将事件源传入的所有事件路由到 Channel。以下示例创建了一个可以倒数计数的 Channel。
function* countdown(secs) {
return eventChannel(emitter => {
const interval = setInterval(() => {
secs -= 1;
if (secs > 0) {
emitter(secs);
} else {
// 发送 END 将导致 Channel 关闭。
emitter(END);
}
}, 1000);
// 回传一个 unsubscribe 函数。
return () => {
clearInterval(interval);
};
});
}
除此之外,还可以通过创建一个独立的 Channel 来在不同的 Saga 之间进行通信。Channel 可以使用 put
手动推送,还可以通过 take
手动取出,并以此来完成 Saga 之间的通信。