Hacer promesas creadas dinámicamente en secuencia.

¿Cómo puedo crear dinámicamente una serie de promesas y hacer que se ejecuten en secuencia?

pseudocode for x=0 to maxValue promiseArray.push(createNewPromise(x)) executeAllPromisesSequentially(promiseArray) 

dónde

 executeAllPromisesSequentially is functionally equivalent to promise1() .then(promise2) .then(promise3) etc ... 

Hay algunos patrones mostrados en mi esencia

Promover la iteración con Reducir

 let tasks = [ /* ... */ ] let promise = tasks.reduce((prev, task) => { return prev.then(() => { return task(); }); }, Promise.resolve()); promise.then(() => { //All tasks completed }); 

Patrón de iteración secuencial

 let tasks = [ /* ... */ ] let promise = Promise.resolve(); tasks.forEach(task => { promise = promise.then(() => { return task(); }); }); promise.then(() => { //All tasks completed }); 

Ejemplo de iteración secuencial

 function spiderLinks(currentUrl, body, nesting) { let promise = Promise.resolve(); if(nesting === 0) { return promise; } const links = utilities.getPageLinks(currentUrl, body); links.forEach(link => { promise = promise.then(() => spider(link, nesting - 1)); }); return promise; } 

Solo construye una cadena como dijo jaromandaX . Sin embargo, debe asegurarse de que utiliza let dentro del bucle para cerrar la x:

  let chain = Promise.resolve(); const promises = []; for(let x = 0; x < maxValue; x++) promises.push(chain = chain.then(() => createNewPromise(x))); 

La reducción o el encadenamiento de bucle / recursión viene a la mente como una práctica común, sin embargo, si desea mantener y acceder a las resoluciones intermedias aquí, tengo otro enfoque al utilizar una invención de la función scanl de Haskell en JS.

scanl es similar a JS .reduce() pero como .map() siempre devuelve una matriz del mismo tamaño que contiene los valores provisionales. Así que la función scanl se vería algo así;

 var scanl = (xs, f, acc) => xs.map((a => e => a = f(a,e))(acc)); 

Así que si lo haces;

 scanl([1,2,3,4], (a,e) => a + e, 0) // -> [1,3,6,10] 

Por lo scanl ahora que tenemos scanl a la mano, podemos intentar secuenciar promesas manteniendo las resoluciones intermedias en una matriz resultante.

 var scanl = (xs, f, acc) => xs.map((a => e => a = f(a,e))(acc)), proms = Array(5).fill().map((_,i) => new Promise((v,x) => setTimeout(v,100+Math.random()*1900,`res ${i+1}`))); proms = scanl(proms, (a,p,t) => a.then(v => (t = v, p)) .then(v => `${t} and ${v}`) .then(s => (console.log(`did stg with ${s}`),s)), Promise.resolve("init 0")); Promise.all(proms) .then(vs => vs.forEach(v => console.log(v))); 
 .as-console-wrapper { max-height : 100% !important }