Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Custom middleware per azioni asincrone

Sfruttare il concetto di middleware disponibile su Redux per implementare il meccanismo della gestione delle azioni asincrone.
Sfruttare il concetto di middleware disponibile su Redux per implementare il meccanismo della gestione delle azioni asincrone.
Link copiato negli appunti

La soluzione basata sul middleware thunk vista nella lezione precedente, risolve elegantemente il problema della gestione delle azioni asincrone con Redux. Tuttavia, essa costringe a complicare il codice dell'action creator che si dovrà occupare di effettuare la chiamata HTTP e di gestire la risposta. Se, come spesso accade, la nostra applicazione interagisce pesantemente con il server, ci troveremo ad avere tanto codice duplicato (o comunque abbastanza simile) all'interno degli action creator, snaturandolo del suo obiettivo originario: creare un'azione in base a dei parametri. Probabilmente in questi casi è opportuno ripensare un po' l'approccio alla gestione delle azioni asincrone, introducendo un middleware ad hoc. L'obiettivo è di isolare il codice che si occupa delle chiamate al server in un apposito middleware è di ripristinare il compito originario all'action creator.

L'infrastruttura che andiamo a creare può essere riassunta dal seguente diagramma:

Rispetto all'architettura presentata in precedenza negli analoghi diagrammi, qui abbiamo la presenza di un middleware che interagisce con il server. Vediamo come realizzare questa infrastruttura.

Partiamo innanzitutto con la definizione di uno schema di azione che possa contenere le informazioni generali per effettuare una chiamata HTTP. La seguente potrebbe essere una possibile definizione:

const httpActionTemplate = {
type: "",
endpoint: null,
verb: "GET",
payload: null,
headers: []
};

Definiamo quindi una costante che identifichi il tipo di meta-azione rappresentante la chiamata HTTP verso il server. Parliamo di meta-azione perché non si tratta dell'azione che andrà a modificare direttamente lo stato della nostra applicazione, ma di un particolare tipo di azione che verrà tradotta in una chiamata HTTP verso il server e che avrà come effetto collaterale la modifica allo stato dell'applicazione. Definiamo quindi una costante che identifichi questo tipo di meta-azione, come mostrato dalla seguente definizione:

const HTTP_ACTION = "HTTP_ACTION";

A questo punto abbiamo bisogno di una funzione che trasformi un'azione diretta verso lo stato di Redux, in una meta-azione con tutte le informazioni per effettuare una chiamata HTTP verso il server. Il seguente è un esempio di funzione che fa al caso nostro:

function httpAction(action) {
return {
[HTTP_ACTION]: Object.assign({}, httpActionTemplate, action)
};
}

Essa prende una azione e restituisce un oggetto la cui unica proprietà ha il nome della meta-azione HTTP_ACTION con valore dato dalla fusione dell'azione con il template visto prima.

In altre parole, l'azione passata alla funzione httpAction() viene eventualmente completata con i dati predefiniti dall'httpActionTemplate.

Vediamo quindi come implementare il middleware che intercetterà la meta-azione ed eseguirà la chiamata HTTP:

store => next => action => {
if (!action[HTTP_ACTION]) {
return next(action);
}
var actionInfo = action[HTTP_ACTION];
next({
type: actionInfo.type + "_REQUESTED"
});
var fetchOptions = {
method: actionInfo.verb,
headers: actionInfo.headers,
body: actionInfo.payload || null
};
return fetch(actionInfo.endpoint, fetchOptions).then(response => json(), error => next({
type: actionInfo.type + "_FAILED",
payload: error
})).then(data => next({
type: actionInfo.type + "_RECEIVED",
payload: data
}));
}

Il middleware analizza l'azione alla ricerca della proprietà HTTP_ACTION. Se l'azione corrente non contiene la proprietà, viene invocato il middleware successivo. In caso contrario, viene generata un'azione il cui type è composto dal type dell'azione originaria seguito dal suffisso _REQUESTED. La nuova azione viene inoltrata al middleware successivo e quindi viene effettuata la chiamata HTTP tramite fecth(). Analogamente all'avvio della richiesta, l'esito della chiamata genera un'azione con suffisso _RECEIVED o _FAILED, anch'essa inoltrata al middleware successivo. Come possiamo immaginare, il middleware appena definito svolge sostanzialmente il medesimo compito della soluzione basata su thunk, ma è una soluzione più generale e meno invasiva della precedente.

L'action creator che consente di generare la meta-azione per ottenere la lista delle attività dal server, potrà essere implementato come segue:

function getListAction() {
return httpAction({
type: GETLIST,
endpoint: "api/todos"
});
}

Come possiamo vedere, la funzione si limita a restituire la meta-azione generata da httpAction() a partire dalle informazioni minime per creare una chiamata HTTP. Il dispatch di questa azione innesca il meccanismo che da origine alla chiamata asincrona ed al relativo aggiornamento dello stato della nostra applicazione.


Ti consigliamo anche