📜 ⬆️ ⬇️

Briefly about redux-saga channels

Good afternoon dear friends.


In this article I would like to describe the mechanism of the redux-saga channels as simple and concise as possible, using examples close to real cases, I hope it happened to me.


So, let's begin.


Watch-and-fork problem


Suppose that we have the usual watch-and-fork model, of the following form:


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

This approach is bad because when catching several INIT_REQUEST events INIT_REQUEST one after another, several makeRequest executions will be launched, respectively. Which in turn can cause their “race”.


And here the channel mechanism comes to our rescue.


The channels have buffers, thereby helping to queue INIT_REQUEST events (for example, INIT_REQUEST ), and organize their sequential execution (for example, makeRequest will makeRequest executed sequentially several times).


Roughly speaking, the channels form a FIFO queue for sequential execution.


They are classified by event source:



So, let's briefly analyze each.


More about channel


Such channels usually solve the problem of communication between sagas. Used very rarely. For example, if you need to reconcile several requests that start at the same time.


 channel([buffer]) 

It has a single buffer argument - the accumulating buffer (we'll take a closer look at the buffers below).


Read more about actionChannel


Most often used when it is necessary to respond to events from the redux store.


 actionChannel(pattern, [buffer]) 

Takes two arguments:



Brief example of use:


 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) { //   } 

More on eventChannel


Usually through him solve the problem of communication through the web socket.


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

Takes three arguments:



Brief example of use:


 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') } } 

Surely you have noticed the presence of the constant END - this is an action that means the end of communication with the channel.


In the source code, redux-saga is represented as follows:


 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; }; 

and in the eventChannel source code eventChannel see the following script


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

What is a buffer?


It deserves attention, since each channel has a base buffer, and with it, a queue for processing is formed.


Buffer creation example:


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

buffers are instances of buffer factories with different strategies.


Only 5 strategies, they correspond to the methods:



Instead of


So, we have disassembled why the mechanism of channels was invented, and what practical tasks are used.


Hopefully, after reading, a general idea is formed and the world has become a bit simpler.


')

Source: https://habr.com/ru/post/432070/


All Articles