Si vas a http://localhost:4200/ ahora y juegas con los botones de la moneda, verás que no pasa nada especial. Si observamos el estado actual de la aplicación, es necesario que haya una forma de cargar los tipos de cambio desde una API de datos de divisas dedicada, como fixer.io.
Redux tiene su propia convención para manejar las peticiones del lado del servidor . Lo hace a través de un middleware – una pieza de lógica que se mantiene entre el servidor y las funciones de reducción. En Redux, las peticiones del lado del servidor se consideran como efectos secundarios de acciones que no pueden ser manejadas completamente a través de un reductor. Tales acciones llaman a las funciones impuras , haciendo que los reductores no puedan manejar la recreación de la acción porque la función no depende enteramente de su entrada. Lee más sobre este importante concepto aquí
Acciones para el manejo de los efectos secundarios
La norma para la gestión de las solicitudes del lado del servidor requiere la aplicación de tres medidas:
- Acción que indica el inicio de la solicitud del lado del servidor: Esta acción se envía justo antes de que se haga la solicitud. En la aplicación de ejemplo, el nombre de esta acción se llamará LOAD_CURRENCIES. Un reductor que maneje una acción de este tipo cambiaría una propiedad de estado dedicada para indicar una ubicación del lado del servidor, como loadingCurrencies, que puede utilizarse para implementar un spinner de carga, por ejemplo.
- Acción que indica una solicitud exitosa: Esta acción se envía cuando se hace la solicitud. Su carga útil contiene la respuesta a la solicitud. El reductor simplemente añade la respuesta a su correspondiente propiedad estatal. En el ejemplo, el nombre de esta acción se llamará LOAD_CURRENCIES_SUCCESS y su carga útil llenará la propiedad estatal de tasas con la información más reciente sobre las tasas de la moneda.
- Acción que indica una solicitud fallidaEsta acción se envía si la solicitud falla. La carga útil de la acción puede contener la razón del error o simplemente no devolver nada. En la aplicación de ejemplo, esta acción se llamaría normalmente LOAD_CURRENCIES_FAIL
Para simplificar, omitiremos el proceso de hacer una acción separada que maneje el fracaso . Así es como se ve la implementación de la nueva acción:
123456789101112131415161718192021importación{Acción}de$0027@ngrx/store$0027;exportaciónconstAcciónTipos={CAMBIO_MONEDA:$0027Cambio de moneda$0027,CARGAR_TIPOS DE MONEDA:$0027Cargando tipos de moneda$0027};exportaciónclaseCargaTipos de monedaAcciónAplicacionesAcción{tipo=Tipos de Acción. LOAD_CURRENCY_RATES;constructor(public payload:string){}}clase de exportaciónLoadRatesCompleteActionimplementsAction{type=Tipos de Acción.LOAD_RATES_COMPLETE;constructor(public payload:string){}}}tipo de exportaciónActions=// Agregar las funciones como tpyesLoadCurrencyRatesAction|LoadRatesCompleteAction
ts
¿Qué pasa entre la acción de carga y la acción de éxito o fracaso de la carga?
Aquí es donde el middleware entra en juego. Para ser más exactos, el middleware para el manejo de los efectos secundarios .
En cuanto a las llamadas del lado del servidor, serán manejadas por un servicio Angular 2 , que será llamado dentro del efecto.
Obtención de datos con un servicio
Antes de añadir los efectos, vamos a añadir el servicio que va a buscar los datos de la API de fixer.io.
Crear un directorio de aplicaciones/servicios que contenga los servicios que manejan las solicitudes del lado del servidor y crear un servicio para las monedas:
123$ servicios mkdir$ servicios cd$ monedas de toque.ts
bash
El servicio se ve así:
123456789101112131415161718importar{Http}de$0027@angular/http$0027;importar{inyectar}de$0027@angular/núcleo$0027;@inyectar()exportclassCurrencyService{constructor(privado http:Http){}cargarCurrencies(){//Informar que la base es USDregresar esto. http.get($0027http://api.fixer.io/latest?base=USD$0027).map((response)={{{{let body = response.json();return body.rates})}}
ts
CurrencyService contiene una función, loadCurrencies(), que realiza una simple solicitud HTTP a la API de fixer.io y devuelve las tasas propiedad de la respuesta como un observable.
Implementar un efecto
A continuación, vamos a implementar el efecto secundario para el manejo de las tasas de devolución de CurrencyService.
En Angular 2, hay un paquete especial para manejar los efectos secundarios – ngrx/efectos
Abra su terminal y escriba:
1npminstall @ngrx/efectos --save
bash
Crear un directorio de aplicaciones/efectos y un archivo de los efectos relativos a las monedas:
123 $ mkdir effects $ cd effects $ touch currencies.ts
bash
123456789101112131415161718192021222324252627// app/effects/operations.tsimport{Injectable}de$0027@angular/core$0027;import{Effect,Actions}de$0027@ngrx/effects$0027;import{Observable}de$0027rxjs/Observable$0027;import*como monedaActions from$0027. ./acciones/monedas$0027;importar{Servicio de moneda}de$0027../servicios/servicio de moneda$0027;importar{Tasa de cargaAcción completa}de$0027.. /acciones/monedas";@Injectable()exportclassCurrencyEffects{constructor(privado _acciones:Acciones,privado _servicio de moneda:Servicio de moneda){}/* Los efectos para los diferentes estados son singletons que $0027interceptan$0027 acciones despachadas que están siendo enviadas al reductor. */ @Efecto() loadCategories$ =this._actions.ofType(currencyActions.ActionTypes.LOAD_CURRENCY_RATES).switchMap(()= >este._currencyService. loadCurrencies().map((rates)= >newLoadRatesCompleteAction(rates)).catch(()= >Observable.of(newLoadRatesCompleteAction({})));}
ts
_actions.ofType() devuelve un observable que observa los eventos recién enviados que coinciden con el tipo de la acción. switchMap() es un operador rxJS. Forma parte de varios operadores que se usan para la programación reactiva. Lo que hace diferente a switchMap() es que devuelve sólo el valor del observable más reciente en un flujo de observables.
Una vez que el servicio regrese, hay algunas opciones.
- Si los resultados se obtienen con éxito, se creará una nueva LoadRatesCompleteAction, teniendo las tasas como su carga útil.
- Si se ha producido un error, se creará la misma acción, pero con la carga vacía.
- Alternativamente, se puede añadir una LoadRatesFailAction a las monedas/acciones para manejar los casos en los que el servidor no devuelve un resultado.
El último paso para el manejo de los efectos es registrar los efectos en el app.module y la moneda como proveedor:
12345678910111213141516171819// app.module.tsimport{CurrencyEffects}from"./common/effects/currencies";import{EffectsModule}from"@ngrx/effects";import{CurrencyService}from"./common/services/currency.service";//...@NgModule({///... bootstrap y declaraciones importaciones:[// Añadir cada uno de los efectos para cada uno de sus estados en el módulo.EffectsModule.run(CurrencyEffects),],/Añadir el CurrencyService como proveedor proveedores:[CurrencyService]})exportclassAppModule{constructor(){}}
ts
Recuerde que no manejamos el caso en el que los efectos fallaron.