Angular 7 | observables

Los observables brindan soporte para compartir datos entre editores y suscriptores en una aplicación angular. Se la conoce como una mejor técnica para el manejo de eventos, la programación asíncrona y el manejo de múltiples valores en comparación con técnicas como las promesas.
Una característica especial de Observables es que solo puede acceder a él un consumidor que se suscriba, es decir, se define una función para publicar valores, pero no la ejecuta el consumidor suscrito (puede ser cualquier componente) solo a través de la cual el cliente puede recibir notificaciones hasta que se ejecute la función o hasta que se suscriban.
Un observable puede entregar múltiples valores de cualquier tipo. La API para recibir valores es la misma en cualquier condición y la configuración y la lógica son manejadas por el observable. El resto solo se trata de suscribirse y darse de baja de la información requerida.
Observadores: para manejar la recepción de mensajes observables, necesitamos una interfaz observable que consta de métodos de devolución de llamada con respecto a los mensajes de los observables. Algunos de los métodos básicos son los siguientes: 
 

  • siguiente: es un controlador para cada mensaje por observable, puede llamarse cero o más veces después de que comience la ejecución.
    Ejemplo: Es un ejemplo simple para el uso del método next() de los observadores.
     

javascript

import { Component, OnInit } from '@angular/core';
import {Observable} from 'rxjs';
  
@Component({
    selector: 'app-next-example',
    templateUrl: './next-example.component.html',
    styleUrls: ['./next-example.component.css']
})
 
export class NextExampleComponent implements OnInit {
  
    constructor() { }
  
    ngOnInit() {
     
        // Create a new Observable
        const sqnc = new Observable(countOnetoTen);
      
        // Execute the Observable and print the
        // result of each notification
        // next() is a call to countOnetoTen method
        // to get the next value from the observable
        sqnc.subscribe({
            next(num) { console.log(num); }
        });
         
        // This function runs when subscribe()
        // is called
        function countOnetoTen(observer) {
             
            for(var i = 1; i <= 10; i++) {
                 
                // Calls the next observable
                // notification
                observer.next(i);
            }
         
            // Unsubscribe after completing
            // the sequence
            return {unsubscribe(){}};
        }
    }
}
  • Producción: 
     

  •  
  • error: Es un controlador para cada mensaje de error. Un error detiene la ejecución de la instancia observable.
    Ejemplo: este es un ejemplo, el error se induce intencionalmente en el código para comprender cómo funciona el error.
     

javascript

import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs';
  
@Component({
    selector: 'app-error-example',
    templateUrl: './error-example.component.html',
    styleUrls: ['./error-example.component.css']
})
 
export class ErrorExampleComponent implements OnInit {
  
    constructor() { }
  
    ngOnInit() {
     
        // Create a new Observable
        const sqnc = new Observable(generateError);
      
        // Execute the Observable and print the
        // result of each notification
        // error() is called when next generate
        // some error
        sqnc.subscribe({
            next(num) { },
            error(err) { console.log('Error Somewhere')}
        });
         
        // This function runs when subscribe() is called
        function generateError(observer){
             
            // Calls the next observable notification
            // It generates an error and error is called
            observer.next( adddlert("Welcome guest!"));
             
            // Unsubscribe after completing the sequence
            return {unsubscribe(){}};
        }
    }
  
}
  • Producción: 
     

  • complete: Es un identificador en el que se notifica la finalización de la ejecución observable.
    Ejemplo: Este ejemplo muestra el uso de la función completa. La notificación de finalización la activa el observador después de la finalización de la ejecución del observable.
     

javascript

import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs';
  
@Component({
    selector: 'app-complete-example',
    templateUrl: './complete-example.component.html',
    styleUrls: ['./complete-example.component.css']
})
 
export class CompleteExampleComponent implements OnInit {
  
    constructor() { }
  
    ngOnInit() {
      
        // Create a new Observable
        const sqnc = new Observable(countOnetoTen);
  
        // Execute the Observable and print the
        // result of each notification
        sqnc.subscribe({
            next(num) { console.log(num); },
            complete(){console.log("Completed!!!!")}
        });
         
        // This function runs when subscribe()
        // is called
        function countOnetoTen(observer){
             
            for(var i = 1; i <= 10; i++) {
             
                // Calls the next observable
                // notification
                observer.next(i);
            }
             
            observer.complete();
             
            // Unsubscribe after completing
            // the sequence
            return {unsubscribe(){}};
        }
    }
}
  • Producción: 
     

  •  

Haciendo un Observable: En el siguiente ejemplo, haremos un observable simple para obtener una tabla de 2. Este código está escrito en el archivo app.component.ts. Antes de usar Observables, importe Observables de la biblioteca rxjs escribiendo el siguiente código. 
 

import {Observables} from 'rxjs'

javascript

import { Component } from '@angular/core';
import {Observable} from "rxjs";
import { CompileTemplateMetadata } from '@angular/compiler';
  
@Component({
    selector: 'app-rt',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
})
 
export class AppComponent {
    title = 'MyFirstApp';
}
 
// Create a new Observable that will
// deliver the above sequence
const table = new Observable(tableOfTwo);
  
// Execute the Observable and print the
// result of each notification
// next() is a call to tableOfTwo() method
// to get the next value from the observable
table.subscribe({
    next(num) { console.log(num); },
    complete() { console.log('Finished sequence'); }
});
 
// This function runs when subscribe() is called
function tableOfTwo(observer) {
     
    for(var i = 1; i <= 10; i++) {
      observer.next('2 * ' + i + ' = ' + i*2);
    }
     
    observer.complete();
    return {unsubscribe(){}};
}

En este código, el next() se usa para llamar al siguiente retorno del observable y en el observable, una vez que se completa la tarea, devuelve la función de cancelación de suscripción que conduce a la cancelación de la suscripción del observable y, por lo tanto, no se pueden realizar más requests. Cuando se llama al método complete(), imprime la string ‘Secuencia finalizada’. Toda la funcionalidad se muestra en la consola.
Producción: 
 

Multidifusión: es una práctica de transmitir un observable a una lista de múltiples suscriptores en una sola ejecución. Con la multidifusión observable, no hay múltiples oyentes para registrar en el documento, sino que se reutiliza el primer oyente y los valores se envían a cada suscriptor. Se realiza determinando el observable acerca de si los valores se van a multidifundir o no.
Continuando con el ejemplo anterior, ahora se realizará la operación de multidifusión, que emitirá la misma tabla de dos en dos 2 secuencias y esperará un segundo antes de realizar otra operación.
 

javascript

import { Component, OnInit } from '@angular/core';
import {Observable} from 'rxjs';
  
@Component({
    selector: 'app-my-page',
    templateUrl: './my-page.component.html',
    styleUrls: ['./my-page.component.css']
})
 
export class MyPageComponent implements OnInit {
  
    constructor() { }
  
    ngOnInit() {
     
        const multiSeq = new Observable(this.multiSeqSubs());
    
  
        multiSeq.subscribe({
            next(num) { console.log('1st subscribe: ' + num); },
            complete() { console.log('1st sequence finished.'); }
        });
      
        // Subscribe again After 1 seconds.
        setTimeout(() => {
            multiSeq.subscribe({
                next(num) { console.log('2nd subscribe: ' + num); },
                complete() { console.log('2nd sequence finished.'); }
            });
        }, 1000);
    }
  
    multiSeqSubs() {
        const seq = [];
         
        for (var i = 1; i <= 10; i++) {
             
            // Pushes the string onto sequence
            seq.push('2 * ' + i + '=' + 2*i)
        }  
     
        // Keep track of each observer
        const obs = [];
         
        // A single time Stamp for one
        // set of values being generated,
        // multicasted to each subscriber
        let timeStamp;
    
        // Return the subscriber function
        // (runs when subscribe() function
        // is invoked)
        return (ob) => {
            obs.push(ob);
             
            // When this is the first subscription,
            // start the sequence
            if (obs.length === 1) {
                timeStamp = this.exec_Sequence({
                    next(val) {
                         
                        // Iterate through observers
                        // and notify all subscriptions
                        obs.forEach(o => o.next(val));
                    },
                     
                    complete() {
                         
                        // Notify all complete callbacks
                        obs.slice(0).forEach(o => o.complete());
                    }
                }, seq, 0);
            }
    
            return {
                 
                // Unsubscribe from the observers
                unsubscribe() {
                 
                    obs.splice(obs.indexOf(ob), 1);
                     
                    // Cleanup
                    if (obs.length === 0) {
                        clearTimeout(timeStamp);
                    }
                }
            };
        };
    }
    
    // Executes the sequence
    exec_Sequence(observer, sequence, index) {
        return setTimeout(() => {
            observer.next(sequence[index]);
            if (index === sequence.length - 1) {
                observer.complete();
            } else {
                this.exec_Sequence(observer, sequence, ++index);
            }
        }, 1000);
    }
    
    // Create a new Observable that will
    // deliver the above sequence
}

Este código está haciendo la misma funcionalidad, es decir, manejar operaciones de multidifusión. En este código, tenemos una lista de observadores que depende del no. de suscripciones realizadas para la operación de multidifusión. Aquí, durante la ejecución del código, solo tenemos 2 operaciones que se están ejecutando y, por lo tanto, solo tenemos 2 elementos en la lista ‘obs’.
Producción: 
 

Manejo de errores: 
los observables producen valores asíncronos y, por lo tanto, try/catch no detecta ningún error porque puede provocar la detención del código independientemente de otras tareas que se estén ejecutando en ese momento. En cambio, manejamos los errores especificando una devolución de llamada de error en el observador. Cuando se produce un error, hace que el observable limpie las suscripciones y deje de producir valores para esa suscripción. Un observable puede producir valores (llamar a la siguiente devolución de llamada) o puede completarse, llamando a la devolución de llamada completa o de error.

La sintaxis para la devolución de llamada de error 

observable.subscribe({
    next(val) { console.log('Next: ' + val)},
    error(err) { console.log('Error: ' + err)}
});

Publicación traducida automáticamente

Artículo escrito por piyush25pv y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *