Skip to content

jorgeucano/anglar-resource-rxresource-demo

Repository files navigation

Creación del proyecto

npx @angular/cli@next new http-new-format

angular create

Errores

Si te aparece este error es porque no salio o no tenes actualizado el Angular Language Service, en angular v19 todos los components son standalone por defecto.

angular standalone error

paso 1

Agregamos en app.config.ts la funcionalidad de http provideHttpClient()

export const appConfig: ApplicationConfig = {
  providers: [provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes), provideHttpClient() ]
};

paso 2

inyectamos el HttpClient para hacer las llamadas en app.component.ts

http = inject(HttpClient);

Como haciamos la llamadas anteriormente, en un servicio tendriamos una funcion que llamaria a esto, obviamente que no es lo ideal hacer un subscribe directo, pero como siempre es a modo de ejemplo bien visual Algo parecido a:

this.http
    .get('https://api.adviceslip.com/advice') // get a la url
    .subscribe( // hacemos la llamada
    (value: any) => { // seteamos el tipo del return
        this.advice = value.slip.advice; // usamos los datos
    }
    )

ahora tenemos nuevas formas de hacerlo y con ello vamos a movernos lentamente a signals, paso a paso hasta terminar sin mas rxjs.... hace mucho que lo vengo diciendo, tarde o temprano van a sacar a rxjs para volverlo "optativo".

Resource

Y para esto aparece resource, que lo que nos genera es la posibilidad de manejar lo mismo que haciamos con rxjs pero con signals... sin tanto esfuerzo

Si vamos a la descripcion de resource en el codigo fuente nos dice lo siguiente:

Constructs a Resource that projects a reactive request to an asynchronous operation
 defined by a loader function, which exposes the result of the loading operation via signals.

Por lo tanto, resource lo que va a hacer es via SIGNALS generarnos todo lo necesario para el trabajo de nuestro request. Ahora como funciona:

this.adviceResource = resource({
      loader: () => fetch('https://api.adviceslip.com/advice')
        .then(res => res.json())
    })

    effect(() => {
      console.log('code status:' , ResourceStatus[this.adviceResource.status()]);
      console.log('value: ', this.adviceResource.value()?.slip.advice); 
    })
    

Recorda que el status se maneja por numero/codigo, pero con la constante ResourceStatus que ya viene en @angular/core podemos obtener el valor en texto de este status, y asi poder manejar nuestros loaders o cosas por el estilo. Los 6 valores posibles son:

Idle = 0,      // `value()` will be `undefined`
Error = 1,     // `value()` will be `undefined`
Loading = 2,   // `value()` will be `undefined`
Reloading = 3, // The resource is currently reloading a fresh value for the same request.
               //`value()` will continue to return the previously fetched value during the reloading operation.
Resolved = 4,  // Loading has completed and the resource has the value returned from the loader.
Local = 5      // The resource's value was set locally via `.set()` or `.update()`.

Aca como siempre podemos ver la forma mas facil y sencilla para un ejemplo, resource recibe como parametro un objeto, que dentro tiene loader, loader es una funcion anonima que nos permite tener un fetch (adios RXJS) que de lo que obtenemos vamos a hacer un then y obtener en nuestro caso el json directo.

Como podran ver, esto no esta ejecutandose por asi decirlo, no estamos haciendo mas que dar a un parametro esta nueva funcionalidad, pero lo que podemos hacer, que es parte de la magia de signals, es obtener las modificaciones dentro de un effect.

Tambien el punto importante, es que una vez que resuelva, lo que va a hacer es un abortSignal lo cual nos permite mejorar nuestro rendimiento de memoria sin tener cosas que ya no necesitamos

Ahora que podemos manejar estos efectos directamente como nostoros queramos, vamos a mostrar 2 cosas: 1 - que tenemos el status del fetch por lo tanto podemos usarlo para mostrar loaders o manejar cosas dentro de nuestras excepciones si llega a fallar. 2 - el retorno del valor, el cual sera undefined hasta que tenga un valor apropiado.

<h1>adviceResource: [{{ resourceStatus[this.adviceResource.status()] }}]</h1>
@if (this.adviceResource.status() === 2) {
    <loading-spinner />
}
@else if (this.adviceResource.status() === 4) {
  <h1>{{ this.adviceResource.value()?.slip.advice }}</h1>
}

costos de migración

hay una realidad, que es muy costoso hacer migraciones en codebases reales, no podemos hacer esto tan facil, como en cualquier demo, por lo tanto, tenemos una opcion que es un intermedio de estas dos opciones.

RxResource

Algo que el equipo de Angular tiene en cuenta, es esto que menciono arriba, ya que ellos tienen muchisimas apps internas realizadas con angular, y eso les genera pensar como hacer lo mas facil posible las migraciones y que se pueda avanzar de a poco, y para eso crearon el rxResource que es un intermedio entre las dos cosas que vimos anteriormente.

this.adviceRxResource = rxResource({
      loader: () =>  this.http.get<any>('https://api.adviceslip.com/advice')
    });

Si, el ejemplo te lo demuestra de la forma mas facil, el cambio es un mix entre ambos, tenemos el rxResource, que va a hacer todo por nosotros, hasta el desubscribirse, tal y como en resource hace un abortSignal, el codigo de la llamada sigue siendo el http.get de siempre, y el resto es casi identico a el resource, por lo tanto nos deja ir migrando poco a poco nuestro codigo, para poder manejar las cosas de una forma corecta.

En tanto el html se veria identico al de resource

<h1>adviceRxResource: [{{ resourceStatus[this.adviceRxResource.status()] }}]</h1>
@if (this.adviceRxResource.status() === 2) {
    <loading-spinner />
}
@else if (this.adviceRxResource.status() === 4) {
  <h1>{{ this.adviceRxResource.value()?.slip.advice }}</h1>
}

Como parametrizamos?

Una cosa interesante, es como manejamos los parametros, como vamos a agregar cosas a nuestras llamadas, simplemente marcando datos y rellamando y demas? La realidad, es que no, vamos a manejarnos cada vez mas con las reactivas primitivas y esto va a ser un GOLAZO de mitad de cancha, porque vamos a escribir menos codigo y vamos a ser mas eficientes.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published