Creating a promise chain in a for loop

Asked
Active3 hr before
Viewed126 times

9 Answers

chaincreatingpromise
90%

Thanks for contributing an answer to Stack Overflow!, Stack Overflow for Teams Where developers & technologists share private knowledge with coworkers , Stack Overflow help chat , Meta Stack Overflow

You have to assign the return value of .then back to chain:

chain = chain.then(() => getProm(i))
   .then(Wait)

Now you will basically be doing

chain
   .then(() => getProm(1))
   .then(Wait)
   .then(() => getProm(2))
   .then(Wait)
   .then(() => getProm(3))
   .then(Wait)
// ...

instead of

chain
   .then(() => getProm(1))
   .then(Wait)

chain
   .then(() => getProm(2))
   .then(Wait)

chain
   .then(() => getProm(3))
   .then(Wait)
// ...
load more v
88%

One of the great things about using promises is chaining.,With modern functions, we attach our callbacks to the returned promises instead, forming a promise chain:,Creating a Promise around an old callback API,Basically, each promise represents the completion of another asynchronous step in the chain.

function successCallback(result) {
   console.log("Audio file ready at URL: " + result);
}

function failureCallback(error) {
   console.error("Error generating audio file: " + error);
}

createAudioFileAsync(audioSettings, successCallback, failureCallback);
load more v
72%

(async function loop() {
   for (let i = 0; i < 10; i++) {
      await new Promise(resolve => setTimeout(resolve, Math.random() * 1000));
      console.log(i);
   }
})();
65%

You can build up a chain of promises:,$q.when is used to kick off the chain with a resolved promise.,When you queue up promises like above, they all start at the same time. But what if you want them to run in the order you called them?,90+ screencast lessons

for (var i = 0; i < 5; i++) {
   $http.get('/data' + i);
}
// At this point, all the requests will have fired...
// But probabaly, none of them have finished
load more v
75%

A handler, used in .then(handler) may create and return a promise.,In practice we rarely need multiple handlers for one promise. Chaining is used much more often.,To make the chain extendable, we need to return a promise that resolves when the avatar finishes showing.,When a handler returns a value, it becomes the result of that promise, so the next .then is called with it.

new Promise(function(resolve, reject) {

   setTimeout(() => resolve(1), 1000); // (*)

}).then(function(result) { // (**)

   alert(result); // 1
   return result * 2;

}).then(function(result) { // (***)

   alert(result); // 2
   return result * 2;

}).then(function(result) {

   alert(result); // 4
   return result * 2;

});
load more v
40%

This article will discuss executing promises serially (wait for one to complete before moving on to the next). This is an extremely common pattern if you are inside of a loop and want to process something one at a time.,we would chain the promises as such.,Pretty cool right? That's all there is to it.,The last step is taking the above code and putting it in a loop. We will collapse the manual steps of reassignment and put it inside a loop.

For instance some how to do the following:

for (let i = 0; i < 10; i++) {
   // doSomethingAsync
}
load more v
22%

First, create a new promise that resolves to the value 10 after 3 seconds:,Summary: in this tutorial, you will learn about the JavaScript promise chaining pattern that chains promises to execute asynchronous operations in sequence.,In this tutorial, you have learned about the promise chain that executes multiple asynchronous tasks in sequence.,The following picture illustrates the promise chaining:

First, create a new promise that resolves to the value 10 after 3 seconds:

.wp - block - code {
      border: 0;
      padding: 0;
   }

   .wp - block - code > div {
      overflow: auto;
   }

   .shcb - language {
      border: 0;
      clip: rect(1 px, 1 px, 1 px, 1 px); -
      webkit - clip - path: inset(50 % );
      clip - path: inset(50 % );
      height: 1 px;
      margin: -1 px;
      overflow: hidden;
      padding: 0;
      position: absolute;
      width: 1 px;
      word - wrap: normal;
      word - break: normal;
   }

   .hljs {
      box - sizing: border - box;
   }

   .hljs.shcb - code - table {
      display: table;
      width: 100 % ;
   }

   .hljs.shcb - code - table > .shcb - loc {
      color: inherit;
      display: table - row;
      width: 100 % ;
   }

   .hljs.shcb - code - table.shcb - loc > span {
      display: table - cell;
   }

   .wp - block - code code.hljs: not(.shcb - wrap - lines) {
      white - space: pre;
   }

   .wp - block - code code.hljs.shcb - wrap - lines {
      white - space: pre - wrap;
   }

   .hljs.shcb - line - numbers {
      border - spacing: 0;
      counter - reset: line;
   }

   .hljs.shcb - line - numbers > .shcb - loc {
      counter - increment: line;
   }

   .hljs.shcb - line - numbers.shcb - loc > span {
      padding - left: 0.75 em;
   }

   .hljs.shcb - line - numbers.shcb - loc::before {
      border - right: 1 px solid #ddd;
      content: counter(line);
      display: table - cell;
      padding: 0 0.75 em;
      text - align: right; -
      webkit - user - select: none; -
      moz - user - select: none; -
      ms - user - select: none;
      user - select: none;
      white - space: nowrap;
      width: 1 % ;
   }
let p = new Promise((resolve, reject) => {
   setTimeout(() => {
      resolve(10);
   }, 3 * 100);
});
Code language: JavaScript(javascript)
load more v
60%

p3.catch returns a brand new p4 promise, which will react if p3 is rejected., p3.catch returns a brand new p4 promise, which will react if p3 is rejected. ,p2.catch returns a brand new p3 promise, which will react if p2 is rejected., p2.catch returns a brand new p3 promise, which will react if p2 is rejected.

As an example, let’s take a look at the new fetch API for the browser. This API is a simplification of XMLHttpRequest. It aims to be super simple to use for the most basic use cases: making a GET request against an HTTP resource. It provides an extensive API that caters to advanced use cases, but that’s not our focus for now. In its most basic incarnation, you can make a GET /items HTTP request using a piece of code like the following.

fetch('/items')

The fetch('/items') statement doesn’t seem all that exciting. It makes a “fire and forget” GET request against /items, meaning you ignore the response and whether the request succeeded. The fetch method returns a Promise. You can chain a callback using the .then method on that promise, and that callback will be executed once the /items resource finishes loading, receiving a response object parameter.

fetch('/items').then(response => {
   // do something
})

The following bit of code displays the promise-based API with which fetch is actually implemented in browsers. Calls to fetch return a Promise object. Much like with events, you can bind as many reactions as you’d like, using the .then and .catch methods.

const p = fetch('/items')
p.then(res => {
   // handle response
})
p.catch(err => {
   // handle error
})

Reactions passed to .then can be used to handle the fulfillment of a promise, which is accompanied by a fulfillment value; and reactions passed to .catch are executed with a rejection reason that can be used when handling rejections. You can also register a reaction to rejections in the second argument passed to .then. The previous piece of code could also be expressed as the following.

const p = fetch('/items')
p.then(
   res => {
      // handle response
   },
   err => {
      // handle error
   }
)

Another alternative is to omit the fulfillment reaction in .then(fulfillment, rejection), this being similar to the omission of a rejection reaction when calling .then. Using .then(null, rejection) is equivalent to .catch(rejection), as shown in the following snippet of code.

const p = fetch('/items')
p.then(res => {
   // handle response
})
p.then(null, err => {
   // handle error
})

Traditionally JavaScript relied on callbacks instead of promises and chaining. If the fetch function asked for a callback, you’d have to add one that would then get executed whenever the fetch operation ends. Typical asynchronous code flow conventions in Node.js established a best practice of reserving the first parameter in the callback for errors—that may or may not occur—during the fetching process. The rest of the parameters can be used to read the results of the asynchronous operation. Most commonly, a single data parameter is used. The next bit of code shows how fetch would look if it had a callback-based API.

fetch('/items', (err, res) => {
   if (err) {
      // handle error
   } else {
      // handle response
   }
})

Besides traditional callbacks, another API design choice might have been to use an event-driven model. In this case the object returned by fetch would be able to register callbacks for different kinds of events, binding as many event handlers as needed for any events—just like when you attach event listeners to the browser DOM. Typically there’s an error event that’s raised when things go awry, and other events that are raised when something notable happens. In the following piece of code, we show how fetch would look if it had an event-based API.

fetch('/items')
   .on('error', err => {
      // handle error
   })
   .on('data', res => {
      // handle response
   })

A promise is created by passing the Promise constructor a resolver that decides how and when the promise is settled, by calling either a resolve method that will settle the promise in fulfillment or a reject method that’d settle the promise as a rejection. Until the promise is settled by calling either function, it’ll be in a pending state and any reactions attached to it won’t be executed. The following snippet of code creates a promise from scratch where we’ll wait for a second before randomly settling the promise with a fulfillment or rejection result.

new Promise(function(resolve, reject) {
   setTimeout(function() {
      if (Math.random() > 0.5) {
         resolve('random success')
      } else {
         reject(new Error('random failure'))
      }
   }, 1000)
})

Promises can also be created using Promise.resolve and Promise.reject. These methods create promises that will immediately settle with a fulfillment value and a rejection reason, respectively.

Promise
   .resolve({
      result: 123
   })
   .then(data => console.log(data.result))
// <- 123

A reaction may return a value, which would cause the promise returned by .then to become fulfilled with that value. In this sense, promises can be chained to transform the fulfillment value of the previous promise over and over, as shown in the following snippet of code.

Promise
   .resolve(2)
   .then(x => x * 7)
   .then(x => x - 3)
   .then(x => console.log(x))
// <- 11

A reaction may return a promise. In contrast with the previous piece of code, the promise returned by the first .then call in the following snippet will be blocked until the one returned by its reaction is fulfilled, which will take two seconds to settle because of the setTimeout call.

Promise
   .resolve(2)
   .then(x => new Promise(function(resolve) {
      setTimeout(() => resolve(x * 1000), x * 1000)
   }))
   .then(x => console.log(x))
// <- 2000

A reaction may also throw an error, which would cause the promise returned by .then to become rejected and thus follow the .catch branch, using said error as the rejection reason. The following example shows how we attach a fulfillment reaction to the fetch operation. Once the fetch is fulfilled the reaction will throw an error and cause the rejection reaction attached to the promise returned by .then to be executed.

const p = fetch('/items')
   .then(res => {
      throw new Error('unexpectedly')
   })
   .catch(err => console.error(err))
load more v
48%

Promise Inside For/ForEach Loop,Create a folder called promise_loop. Initialize the project folder using npm.,How To Handle Promise Inside Loop,How To Handle Promise Inside Promise

mkdir promise_loop
cd promise_loop
npm init
load more v

Other "chain-creating" queries related to "Creating a promise chain in a for loop"