En bref sur les chaînes redux-saga

Bonjour, chers amis.


Dans cet article, je voudrais décrire le mécanisme des canaux redux-saga aussi simple et concis que possible, en utilisant des exemples proches de cas réels, j'espère que cela a fonctionné pour moi.


Commençons donc.


Problème de modèle Watch-and-Fork


Supposons que nous ayons un modèle de montre et de fourche régulier, de la forme suivante:


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

Cette approche est mauvaise car lors de la capture de plusieurs événements INIT_REQUEST qui se succèdent, plusieurs exécutions de makeRequest seront makeRequest , respectivement. Ce qui à son tour peut les amener à «courir».


Et ici, le mécanisme du canal vient à notre aide.


Les canaux ont des tampons, ce qui aide à aligner les événements entrants (par exemple, INIT_REQUEST ) et à organiser leur exécution séquentielle (par exemple, makeRequest sera exécuté plusieurs fois de manière séquentielle).


En gros, les canaux forment une file d'attente FIFO pour une exécution séquentielle.


Classer par source d'événement:


  • channel - les événements sont mis en file d'attente manuellement à l'aide de put ;
  • actionChannel - les événements sont interceptés près du magasin redux;
  • eventChannel - une source d'événement externe, le plus souvent une socket Web;

Nous allons donc analyser brièvement chacun.


Plus sur la chaîne


Ces canaux résolvent généralement le problème de la communication entre les sagas. Utilisé très rarement. Par exemple, si vous devez coordonner plusieurs demandes en même temps.


 channel([buffer]) 

Il a un seul argument de buffer - le tampon accumulé (nous examinerons les tampons plus en détail ci-dessous).


En savoir plus sur actionChannel


Il est le plus souvent utilisé lorsqu'il est nécessaire de répondre aux événements du magasin redux.


 actionChannel(pattern, [buffer]) 

Il faut deux arguments:


  • pattern - le modèle des événements souhaités, ainsi que take ;
  • buffer - buffer accumulation;

Un bref exemple d'utilisation:


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

Plus sur eventChannel


Habituellement, ils résolvent le problème de la communication via la prise Web à travers elle.


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

Il faut trois arguments:


  • subscribe est une fonction qui initialise une source d'événement externe (dans l'exemple ci-dessous, setTimeout). Dans les arguments, un rappel est appelé émetteur, qui sera appelé lorsqu'il est nécessaire d'envoyer des données au canal depuis la source. La fonction de retour doit se désinscrire;
  • buffer - buffer accumulation;
  • matcher - fonction de filtrage des messages entrants.

Un bref exemple d'utilisation:


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

Vous avez sûrement remarqué la présence de la constante END - c'est l'action, ce qui signifie la fin de la communication avec le canal.


Dans le code source, redux-saga est représenté comme suit:


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

et dans le code source eventChannel voyons le script suivant


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

Qu'est-ce que le tampon?


Il est à noter, puisque chaque canal a un tampon de base, et avec lui, une file d'attente pour le traitement est formée.


Exemple de création d'un tampon:


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

buffers sont une instance d'une fabrique pour créer des tampons avec différentes stratégies.


Seules 5 stratégies, méthodes leur correspondent:


  • buffers.none() - pas de mise en mémoire tampon, les nouveaux messages seront perdus s'il n'y a pas de participants en attente;
  • buffers.fixed(limit) - les nouveaux messages seront mis en mémoire tampon à la limite. Une erreur de débordement entraînera une exception. La limite par défaut est 10;
  • buffers.expanding(initialSize) - comme fixe, mais un débordement provoquera une expansion dynamique du tampon;
  • buffers.dropping(limit) est identique à fixed, mais le débordement buffers.dropping(limit) silencieusement les messages;
  • buffers.sliding(limit) est identique à fixed, mais le débordement ajoutera un nouveau message à la fin et supprimera le message le plus ancien dans le tampon.

Au lieu de fermer


Nous avons donc examiné pourquoi le mécanisme de canal a été inventé et dans quelles tâches pratiques sont utilisées.


J'espère qu'après avoir lu l'idée générale et le monde est devenu un peu plus facile.

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


All Articles