es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Implementación personalizada de distinctUntilChanged

En nuestra aplicación Angular, usamos distinctUntilChanged() con bastante frecuencia y estamos en un punto en el que queremos usarlo para comparar directamente form.valueChanges. Como se describe en esta pregunta: https://stackoverflow.com/a/53825991/1003686, usar distinctUntilChanged en form.valueChanges no funcionará correctamente:

this.myFormControl.valueChanges
  .pipe(distinctUntilChanged())
  .subscribe(newValue => {
    console.log('se dispara infinitamente');
  });

En cambio, tengo que escribirlo de la siguiente manera para que funcione una comparación básica:

this.searchAndFilterForm.valueChanges
  .pipe(distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b))
  .subscribe(newValue => {
    console.log('se dispara solo en cambios reales');
  });

No quiero definir una comparación personalizada en cada cambio de valor del formulario y en su lugar quiero tener un nuevo operador de tubería llamado formDistinctUntilChanged() que pueda usar y refactorizar si es necesario.

Vi que distinctUntilChanged() es un MonoTypeOperatorFunction. ¿Cómo puedo implementar un MonoTypeOperatorFunction personalizado para obtener un operador formDistinctUntilChanged()? Preferiblemente, solo usando el distinctUntilChanged normal con una comparación predefinida.

Básicamente, estoy buscando algo que haga lo mismo que el distinctUntil normal, pero con una comparación predefinida que pueda reutilizar en varios componentes.

this.myFormControl.valueChanges
  .pipe(formDistinctUntilChanged())
  .subscribe(newValue => {
    console.log('se dispara solo en cambios reales');
  });

Crear un operador personalizado de RxJS como se describe en https://tane.dev/2021/01/creating-custom-rxjs-operators/ no funciona realmente en mi entorno Angular porque tenemos eslint (prefer-arrow/prefer-arrow-functions) definido y no entiendo completamente cómo usar otro MonoTypeOperatorFunction en un MonoTypeOperatorFunction.

Tags:  ,

Answer

  1. Avatar for davy.ai

    Para crear un operador de tubería personalizado formDistinctUntilChanged() que utilice el operador distinctUntilChanged() con una función de comparación predefinida, puedes definir una función que devuelva una MonoTypeOperatorFunction con la lógica de comparación deseada.

    Aquí tienes un ejemplo de cómo puedes crear el operador formDistinctUntilChanged():

    import { MonoTypeOperatorFunction } from 'rxjs';
    import { distinctUntilChanged } from 'rxjs/operators';
    
    function formDistinctUntilChanged<t>(): MonoTypeOperatorFunction<t> {
      return distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b));
    }
    

    Esta función devuelve una MonoTypeOperatorFunction que utiliza distinctUntilChanged() con una función de comparación predefinida que comprueba la igualdad profunda utilizando JSON.stringify().

    Para utilizar el operador formDistinctUntilChanged(), simplemente puedes encadenarlo en tu observable valueChanges, de la siguiente manera:

    this.myFormControl.valueChanges
      .pipe(formDistinctUntilChanged())
      .subscribe(newValue => {
        console.log('solo se dispara en cambios reales');
      });
    

    Esto asegurará que el observable solo emita valores cuando haya un cambio real en el valor del formulario. Puedes reutilizar este operador en múltiples componentes, sin necesidad de definir una función de comparación personalizada en cada observable form.valueChanges.

    Ten en cuenta que si prefieres definir tu operador como una función de flecha, puedes utilizar la siguiente sintaxis:

    const formDistinctUntilChanged = <t>(): MonoTypeOperatorFunction<t> =>
      distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b));
    

    Sin embargo, esto puede requerir que actualices tus reglas de eslint.

Comments are closed.