Guten Tag, liebe Freunde.
In diesem Artikel möchte ich den Mechanismus der Redux-Saga-Kanäle so einfach und präzise wie möglich beschreiben. Ich hoffe, dass dies für mich funktioniert hat.
Also fangen wir an.
Problem mit dem Watch-and-Fork-Modell
Angenommen, wir haben ein reguläres Uhrenmodell in der folgenden Form:
import { take, fork } from 'redux-saga/effects' function* watchRequest() { while (true) { const {payload} = yield take('INIT_REQUEST');
Dieser Ansatz ist schlecht, da beim Abfangen mehrerer INIT_REQUEST
Ereignisse, die nacheinander folgen, jeweils mehrere makeRequest
Ausführungen makeRequest
werden. Was wiederum dazu führen kann, dass sie „rennen“.
Und hier hilft uns der Kanalmechanismus.
Kanäle haben Puffer, wodurch eingehende Ereignisse (z. B. INIT_REQUEST
) ausgerichtet und ihre sequentielle Ausführung organisiert werden können (z. B. wird makeRequest
mehrmals nacheinander ausgeführt).
Grob gesagt bilden Kanäle eine FIFO-Warteschlange für die sequentielle Ausführung.
Nach Ereignisquelle klassifizieren:
- Kanalereignisse werden manuell mit
put
die Warteschlange put
. actionChannel
- Ereignisse werden in der Nähe des Redux-Speichers abgefangen.eventChannel
- eine externe Ereignisquelle, meistens ein Web-Socket;
Wir werden also jeweils kurz analysieren.
Mehr zum Kanal
Solche Kanäle lösen normalerweise das Problem der Kommunikation zwischen Sagen. Sehr selten verwendet. Zum Beispiel, wenn Sie mehrere Anforderungen gleichzeitig koordinieren müssen.
channel([buffer])
Es hat ein einzelnes buffer
- den akkumulierenden Puffer (wir werden die Puffer unten genauer untersuchen).
Mehr zu actionChannel
Es wird am häufigsten verwendet, wenn auf Ereignisse aus dem Redux-Speicher reagiert werden muss.
actionChannel(pattern, [buffer])
Es braucht zwei Argumente:
pattern
- das Muster der gewünschten Ereignisse sowie take
;buffer
- Akkumulationspuffer;
Ein kurzes Anwendungsbeispiel:
import { take, actionChannel, call } from 'redux-saga/effects' function* watchRequest() { const requestChannel = yield actionChannel('INIT_REQUEST') while (true) { const {payload} = yield take(requestChannel);
Mehr zu eventChannel
Normalerweise löst es das Problem der Kommunikation über einen Web-Socket.
eventChannel(subscribe, [buffer], [matcher])
Es braucht drei Argumente:
subscribe
ist eine Funktion, die eine externe Ereignisquelle initialisiert (im folgenden Beispiel setTimeout). In den Argumenten wird ein Rückruf als Emitter bezeichnet, der aufgerufen wird, wenn Daten von der Quelle an den Kanal gesendet werden müssen. Return sollte die Funktion abbestellen;buffer
- Akkumulationspuffer;matcher
- Funktion zum Filtern eingehender Nachrichten.
Ein kurzes Anwendungsbeispiel:
import { eventChannel, END } from 'redux-saga' import { take, put, call } from 'redux-saga/effects' function initSocketChannel(query) { return eventChannel(emitter => {
Sicherlich haben Sie das Vorhandensein der END
Konstante bemerkt - dies ist eine Aktion, die das Ende der Kommunikation mit dem Kanal bedeutet.
Im Quellcode wird die Redux-Saga wie folgt dargestellt:
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; };
und im eventChannel
Quellcode sehen eventChannel
das folgende Skript
function eventChannel(subscribe) { … if (isEnd(input)) { close(); return; } ... }
Was ist Puffer?
Es ist bemerkenswert, da jeder Kanal einen Basispuffer hat und damit eine Warteschlange für die Verarbeitung gebildet wird.
Beispiel zum Erstellen eines Puffers:
import { buffers } from 'redux-saga' const buffer = buffers.sliding(5);
buffers
sind eine Instanz einer Fabrik zum Erstellen von Puffern mit unterschiedlichen Strategien.
Nur 5 Strategien, Methoden entsprechen ihnen:
buffers.none()
- keine Pufferung, neue Nachrichten gehen verloren, wenn keine Teilnehmer anstehen;buffers.fixed(limit)
- Neue Nachrichten werden bis zum Limit gepuffert. Ein Überlauffehler führt zu einer Ausnahme. Das Standardlimit ist 10;buffers.expanding(initialSize)
- wie fest, aber ein Überlauf führt dazu, dass der Puffer dynamisch erweitert wird.buffers.dropping(limit)
ist dasselbe wie fest, aber der Überlauf verwirft Nachrichten stillschweigend.buffers.sliding(limit)
ist dasselbe wie fixed, aber ein Überlauf fügt am Ende eine neue Nachricht hinzu und löscht die älteste Nachricht im Puffer.
Anstatt herunterzufahren
Wir haben also untersucht, warum der Kanalmechanismus erfunden wurde und welche praktischen Aufgaben verwendet werden.
Ich hoffe nach dem Lesen der allgemeinen Idee und die Welt ist ein wenig einfacher geworden.