Fluent Async API Javascript

El patron de diseño Fluent es un patron muy util y versatil que no permite encadenar varias llamadas o metodos de una misma clase y luego una vez este todo completado ejecutar otro codigo que realizara la accion final, en muchos casos un builder o una simple llamada a un api.


Con el patron de diseño Fluent podemos realizar cosas como estas:

objecto
    .metodo1()
    .metodo2()
    .completar()

Una implementación simple del método Fluent podria ser la siguiente.

const constructorCasa = {
  elementos: [],
  agregarBase: function() {
    this.elementos.push('Base');

    return this;
  },
  agregarParedes: function() {
    this.elementos.push('Paredes');

    return this;
  },
  agregarTecho: function() {
    this.elementos.push('Techo');

    return this;
  },
  construir: function() {
    console.log('Inicio construccion casa');
    this.elementos.forEach((elemento) => {
      console.log(elemento);
    });
    console.log('Fin construccion casa');
  }
}

constructorCasa
  .agregarBase()
  .agregarParedes()
  .agregarTecho()
  .construir();
  

Este código nos permitir utilizar de una forma versatil una serie de llamadas sobre un mismo objeto, dado que todos los métodos retorna el mismo objeto. Asi como JQuery lo hacia en sus tiempos.

Async

Ahora bien para poder tener el mismo resultado podemos hacerlo de varias formas, al final seria seleccionar la forma que mas no conviene o nos gusta.

Metodo 1

Crear un objeto que guarde cada una de nuestras promesas y al final ejecutar todas estas promesas.

const constructorCasa = {
  tareas: [],
  agregarBase: function() {
    this.elementos.push(Promise.resolve('Base'));

    return this;
  },
  agregarParedes: function() {
    this.elementos.push(Promise.resolve('Paredes'));

    return this;
  },
  agregarTecho: function() {
    this.elementos.push(Promise.resolve('Techo'));

    return this;
  },
  construir: function() {
    Promise.all(this.tareas)
      .then((resultados) => {
        console.log('Inicio construccion casa');
        resultados.forEach((tarea) => {
          console.log(tarea);
        });
        console.log('Fin construccion casa');    
      });
  }
}

constructorCasa
  .agregarBase()
  .agregarParedes()
  .agregarTecho()
  .construir();

Es la misma for en que realizamos el primer ejemplo solo que este trabaja con promesas.

Metodo 2

El siguiente metodo hace uso de una de las caracteristicas de las promesas en Javascript, y es que cualquier objeto que tenga un metodo llamado then podra ser tratado como una promesa.

Este segundo metodo nos permite tanto el uso de then en nuestra cadena de llamadas como el uso de async & await en nuestro codigo.

const constructorCasa = {
  tareas: [],
  agregarBase: function() {
    this.elementos.push(Promise.resolve('Base'));

    return this;
  },
  agregarParedes: function() {
    this.elementos.push(Promise.resolve('Paredes'));

    return this;
  },
  agregarTecho: function() {
    this.elementos.push(Promise.resolve('Techo'));

    return this;
  },
  then: function() {
    return Promise.all(this.tareas)
  }
}

const pasos = await constructorCasa
  .agregarBase()
  .agregarParedes()
  .agregarTecho()

console.log('Inicio construccion casa');
pasos.forEach((tarea) => {
  console.log(tarea);
});
console.log('Fin construccion casa');    

Codigo completo

Ejemplo codigo