简要介绍redux-saga频道

下午好,亲爱的朋友们。


在本文中,我想通过使用接近真实案例的示例来尽可能简明地描述redux-saga通道的机制,希望这一点对我有用。


因此,让我们开始吧。


监视和叉子模型问题


假设我们有以下形式的常规监视和叉子模型:


import { take, fork } from 'redux-saga/effects' function* watchRequest() { while (true) { const {payload} = yield take('INIT_REQUEST'); // ,     yield fork(makeRequest, payload); } } function* makeRequest(payload) { //   } 

这种方法是不好的,因为当捕获几个INIT_REQUEST一个的INIT_REQUEST事件时,将分别makeRequest几个makeRequest执行。 反过来又可能导致他们“竞相”。


在这里,渠道机制对我们有所帮助。


通道具有缓冲区,从而有助于排队进入事件(例如INIT_REQUEST ),并组织其顺序执行(例如, makeRequest将顺序执行几次)。


粗略地说,通道形成了一个FIFO队列,用于顺序执行。


按事件源分类:


  • channel事件使用put手动排队;
  • actionChannel事件在redux商店附近捕获;
  • eventChannel外部事件源,通常是Web套接字;

因此,我们将分别简要分析。


频道更多


这样的渠道通常解决了萨加斯人之间沟通的问题。 很少使用。 例如,如果您需要协调多个请求同时开始。


 channel([buffer]) 

它只有一个buffer参数-累积缓冲区(我们将在下面更详细地检查缓冲区)。


有关actionChannel的更多信息


最常用于必要时响应来自redux存储的事件。


 actionChannel(pattern, [buffer]) 

它有两个参数:


  • pattern所需事件的模式,以及take
  • buffer -累积缓冲区;

使用的简要示例:


 import { take, actionChannel, call } from 'redux-saga/effects' function* watchRequest() { const requestChannel = yield actionChannel('INIT_REQUEST') while (true) { const {payload} = yield take(requestChannel); //      yield call(makeRequest, payload); } } function* makeRequest(payload) { //   } 

有关eventChannel的更多信息


通常,它解决了通过Web套接字进行通信的问题。


 eventChannel(subscribe, [buffer], [matcher]) 

它包含三个参数:


  • subscribe是用于初始化外部事件源的函数(在下面的示例中为setTimeout)。 在参数中,回调称为发射器,当有必要将数据从源发送到通道时,将调用该回调。 返回应退订功能;
  • buffer -累积缓冲区;
  • matcher -过滤传入消息的功能。

使用的简要示例:


 import { eventChannel, END } from 'redux-saga' import { take, put, call } from 'redux-saga/effects' function initSocketChannel(query) { return eventChannel(emitter => { //     web socket const handshakeTimeoutId = setTimeout(() => { emitter('handshake - ok'); }, 100); const messageTimeoutId = setTimeout(() => { emitter('message'); }, 500); const endTimeoutId = setTimeout(() => { emitter(END); }, 1000); //     return () => { clearTimeout(handshakeTimeoutId); clearTimeout(messageTimeoutId); clearTimeout(endTimeoutId); } } ) } export function* saga() { const chan = yield call(initSocketChannel, query) try { while (true) { const message = yield take(chan); //    END   brake console.log(`socket : ${message}`) } } finally { console.log('socket terminated') } } 

您当然会注意到END常量的存在-这是动作,这意味着与通道的通信结束。


在源代码中,redux-saga表示如下:


 var CHANNEL_END_TYPE = '@@redux-saga/CHANNEL_END'; var END = { type: CHANNEL_END_TYPE }; var isEnd = function isEnd(a) { return a && a.type === CHANNEL_END_TYPE; }; 

eventChannel源代码中, eventChannel看到以下脚本


 function eventChannel(subscribe) { … if (isEnd(input)) { close(); return; } ... } 

什么是缓冲区?


值得注意的是,由于每个通道都有一个基本缓冲区,并与之形成了一个处理队列。


创建缓冲区的示例:


 import { buffers } from 'redux-saga' const buffer = buffers.sliding(5); 

buffers是使用不同策略创建缓冲区的工厂实例。


只有5种策略,方法与之相对应:


  • buffers.none() -没有缓冲,如果没有未决的参与者,新消息将丢失;
  • buffers.fixed(limit) -新消息将被缓冲到限制。 溢出错误将导致异常。 默认限制为10;默认限制为10。
  • buffers.expanding(initialSize) -类似于固定值,但溢出将导致缓冲区动态扩展;
  • buffers.dropping(limit)与固定值相同,但是溢出会静默丢弃消息;
  • buffers.sliding(limit)与固定值相同,但是溢出将在末尾添加新消息并删除缓冲区中最旧的消息。

而不是关闭


因此,我们研究了为什么发明了通道机制,以及在实际中使用了哪些任务。


我希望在阅读了总体思路之后,世界变得更加轻松。

Source: https://habr.com/ru/post/zh-CN432070/


All Articles