Boa tarde, queridos amigos.
Neste artigo, gostaria de descrever o mecanismo dos canais redux-saga o mais simples e conciso possível, usando exemplos próximos de casos reais, espero que isso tenha funcionado para mim.
Então, vamos começar.
Problema com o modelo de relógio e garfo
Suponha que tenhamos um modelo regular de relógio e garfo, da seguinte forma:
import { take, fork } from 'redux-saga/effects' function* watchRequest() { while (true) { const {payload} = yield take('INIT_REQUEST');
Essa abordagem é ruim porque, ao capturar vários eventos INIT_REQUEST
que se seguem, várias execuções makeRequest
serão makeRequest
, respectivamente. O que, por sua vez, pode levá-los a "correr".
E aqui o mecanismo do canal vem em nosso auxílio.
Os canais têm buffers, ajudando a alinhar os eventos recebidos (por exemplo, INIT_REQUEST
) e organizando sua execução sequencial (por exemplo, makeRequest
será executado várias vezes sequencialmente).
Grosso modo, os canais formam uma fila FIFO para execução sequencial.
Classifique por origem do evento:
channel
- eventos são enfileirados manualmente usando put
;actionChannel
- eventos são capturados perto da loja redux;eventChannel
- uma fonte de eventos externa, geralmente um soquete da web;
Então, analisaremos brevemente cada um.
Mais no canal
Esses canais geralmente resolvem o problema de comunicação entre sagas. Usado muito raramente. Por exemplo, se você precisar coordenar várias solicitações, iniciando ao mesmo tempo.
channel([buffer])
Ele possui um único argumento de buffer
- o buffer acumulado (examinaremos os buffers em mais detalhes abaixo).
Mais sobre actionChannel
É usado com mais frequência quando é necessário responder a eventos do repositório redux.
actionChannel(pattern, [buffer])
São necessários dois argumentos:
pattern
- o padrão dos eventos desejados, bem como a take
;buffer
- buffer
acumulativo;
Um breve exemplo de uso:
import { take, actionChannel, call } from 'redux-saga/effects' function* watchRequest() { const requestChannel = yield actionChannel('INIT_REQUEST') while (true) { const {payload} = yield take(requestChannel);
Mais sobre eventChannel
Geralmente eles resolvem o problema da comunicação através do soquete da web através dele.
eventChannel(subscribe, [buffer], [matcher])
São necessários três argumentos:
subscribe
é uma função que inicializa uma fonte de eventos externa (no exemplo abaixo, setTimeout). Nos argumentos, um retorno de chamada é chamado emissor, que será chamado quando for necessário enviar dados para o canal a partir da fonte. O retorno deve cancelar a função de inscrição;buffer
- buffer
acumulativo;matcher
- função para filtrar as mensagens recebidas.
Um breve exemplo de uso:
import { eventChannel, END } from 'redux-saga' import { take, put, call } from 'redux-saga/effects' function initSocketChannel(query) { return eventChannel(emitter => {
Certamente você notou a presença da constante END
- isto é ação, o que significa o fim da comunicação com o canal.
No código fonte, redux-saga é representado da seguinte maneira:
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; };
e no código fonte eventChannel
vemos o seguinte script
function eventChannel(subscribe) { … if (isEnd(input)) { close(); return; } ... }
O que é buffer?
É digno de nota, uma vez que cada canal possui um buffer básico e, com ele, uma fila de processamento é formada.
Exemplo de criação de um buffer:
import { buffers } from 'redux-saga' const buffer = buffers.sliding(5);
buffers
são uma instância de uma fábrica para a criação de buffers com estratégias diferentes.
Apenas 5 estratégias, métodos correspondem a eles:
buffers.none()
- sem buffer, novas mensagens serão perdidas se não houver participantes pendentes;buffers.fixed(limit)
- novas mensagens serão armazenadas em buffer até o limite. Um erro de estouro resultará em uma exceção. O limite padrão é 10;buffers.expanding(initialSize)
- como fixo, mas o estouro fará com que o buffer se expanda dinamicamente;buffers.dropping(limit)
é o mesmo que fixo, mas o excesso descartará silenciosamente as mensagens;buffers.sliding(limit)
é o mesmo que fixo, mas o estouro adicionará uma nova mensagem ao final e excluirá a mensagem mais antiga do buffer.
Em vez de desligar
Assim, examinamos por que o mecanismo de canal foi inventado e em que tarefas práticas são usadas.
Espero que, depois de ler a idéia geral, o mundo tenha se tornado um pouco mais fácil.