Выполнение динамически созданных обещаний выполняется последовательно

Как я могу динамически создавать серию обещаний и выполнять их последовательно?

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

где

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

На моем рисунке отображаются некоторые шаблоны

Обещание итерации с уменьшением

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

Последовательный шаблон итерации

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

Пример последовательной итерации

 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; } 

Просто создайте цепочку, как сказал jaromandaX . Однако вам нужно убедиться, что вы используете let внутри цикла для закрытия x:

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

Сокращение или цепочка циклов / рекурсии приходит на ум как обычная практика, однако, если вы хотите сохранить и получить доступ к промежуточным разрешениям, здесь у меня есть другой подход, используя изобретение функции scanl Haskell в JS.

scanl похож на JS .reduce() но подобно .map() всегда возвращает массив того же размера, содержащий промежуточные значения. Таким scanl функция scanl будет выглядеть примерно так:

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

Так что если вы это сделаете;

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

Таким образом, имея scanl под рукой scanl мы можем попытаться выполнить обещания, сохранив промежуточные разрешения в результирующем массиве.

 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 }