Conoce diferir

En un art铆culo anterior , vimos c贸mo crear nuestras propias declaraciones RxJS. Ahora quiero hablar sobre un operador de creaci贸n poco conocido defer, y explicar c贸mo puede usarlo en algunas situaciones.


Suponga que necesita crear un operador que tome una funci贸n y la ejecute solo una vez, la primera vez que recibe un valor. Lo implementamos bajo el nombre tapOnce


function tapOnce<T>(fn: Function): OperatorFunction<T, T> {
  return function(source: Observable<any>) {
    let run = false;
    return source.pipe(
      tap(() => {
        if (!run) {
          fn();
          run = true;
        }
      })
    );
  };
}

El c贸digo es claro: se tapusa para ejecutar la funci贸n, la bandera se runnecesita para hacer esto solo una vez. Ahora usamos el operador.


const source = interval(5000).pipe(
  tapOnce(() => console.log('+')
));

source.subscribe(console.log);

Todo funciona, el signo m谩s se muestra en la consola solo en el primer emite. Ahora agregue los suscriptores.


const source = interval(5000).pipe(
  tapOnce(() => console.log('+')
));

source.subscribe(console.log);
source.subscribe(console.log);

Si miras la consola, solo hay una ventaja. El problema es que ambos suscriptores usan el mismo entorno l茅xico y se refieren a la misma variable run. Necesitamos una forma de posponer la creaci贸n de un hilo hasta que alguien se suscriba.


Ayudar谩 defer


import { defer } from 'rxjs';

function tapOnce<T>(fn: Function): OperatorFunction<T, T> {
  return function(source: Observable<any>) {
    return defer(() => {
      let run = false;
      return source.pipe(
        tap(() => {
          if (!run) {
            fn();
            run = true;
          }
        })
      );
    });
  };
}

El operador deferacepta una funci贸n que deber铆a regresar ObservableInput. El c贸digo dentro deferse ejecutar谩 solo despu茅s de la suscripci贸n, y no durante la creaci贸n. Usando este enfoque y gracias al cierre de js, cada suscriptor usa su propio entorno l茅xico.


Creemos nuestra implementaci贸n simple deferpara una mejor comprensi贸n.


function defer(observableFactory: () => ObservableInput<any>) {
  return new Observable(subscriber => {
    const source = observableFactory();
    return source.subscribe(subscriber);
  });
}

defer devuelve una nueva secuencia, que se crea en el momento de la suscripci贸n por la funci贸n de f谩brica, y se utilizar谩 como fuente.


Aqu铆 hay m谩s ejemplos donde ser谩 煤til defer. Digamos que tenemos una expresi贸n que debe contarse cuando alguien se registra. por ejemplo


const randNum = of(Math.random());

randNum.subscribe(console.log);
randNum.subscribe(console.log);

En este ejemplo, cada suscriptor recibir谩 el mismo valor aleatorio. Puede corregirlo para que la expresi贸n se cuente al suscribirse, no al anunciar.


const randNum = defer(() => of(Math.random()));

randNum2.subscribe(console.log);
randNum2.subscribe(console.log);

// The same concept as using a function
const randNum = () => of(Math.random());
randNum2().subscribe(console.log);
randNum2().subscribe(console.log);

Otro ejemplo es cuando necesita retrasar la ejecuci贸n de una promesa.


// This already executing regardless the numbers of handlers
const promise = new Promise(resolve => {
  resolve();
});

// Deferring the creation of the promise until someone subscribes
const promiseDefered = defer(() => {
  return new Promise(resolve => {
    resolve();
  });
});

promiseDefered.subscribe(console.log);

Las promesas se ejecutan inmediatamente, independientemente del n煤mero de oyentes. Puede hacer que una promesa parezca una corriente (es decir, diferida) usando defer.


All Articles