Intro
Esta es un pequeña técnica que aprendí mientras trabaja con
Promises y es que todos conocemos
Promise.all que nos permite reaccionar respecto a un conjunto de
Promises cuyo orden ejecución es arbitrario.
Pero ¿Qué pasa cuando tenemos un conjunto de
Promises y queremos reaccionar al termino de cada una ellas pero necesitamos que se ejecuten en un determinado orden?
Por ejemplo imagina un proceso de sincronización archivos que recorre una lista y debe actualizar ciertos estados tanto por proceso como en la finalización del mismo.
Setup
Definamos un arreglo con métodos que devolverán Promises
let tasks = [
() => Promise.resolve("a"),
() => Promise.resolve("b"),
() => Promise.resolve("c")
];
Solución
Definimos nuestra función que tomará como parámetros:
- El arreglo de tareas
- Un callback que se ejecutará después de cada tarea y a la cual le pasaremos la salida de la última tarea que se ejecutó.
Además debe regresar un Promise para que podamos atacharnos al final del proceso.
function allInSeq(tasks, afterEach) {
return tasks.reduce((promiseChain, currentTask) => {
return promiseChain
.then(() => currentTask())
.then((r) => {return afterEach(r)});
}, Promise.resolve(true));
}
Para encadenar las tareas usamos el método reduce, que tiene 2 parámetros; un callback que se ejecuta por cada elemento en el arreglo y 1 valor inicial; El valor inicial es importante ya que debemos proporcionar un Promise ya resuelto.
En acción
// Callback que se ejecutará después de cada tarea
function updateUI(r) {
console.log(r);
}
// Llamada a nuestra implementación
allInSeq(tasks, updateUI)
.then(() => { // Se ejecutará al final de todas las tareas
console.log("End");
});
Así de sencillo, espero que les sea de utilidad como lo fue para mí.
Saludos!
Comentarios