What do you know about Promise?

1. Purpose of promise

Promise is a solution for asynchronous programming. The so-called promise is simply a container that holds the results of an event (usually an asynchronous operation) that will end in the future. Syntactically speaking, promise is an object from which you can get the message of asynchronous operation. Promise provides a unified API, and various asynchronous operations can be processed in the same way.

2. How to create a new Promise

const promise = new Promise(function(resolve, reject) {
  // ... some code

  if (/* Asynchronous operation succeeded */){
    resolve(value);
  } else {
    reject(error);
  }
});

3. How to use Promise.prototype.then

Promise instance has a then method, that is, the then method is defined on the prototype object Promise.prototype. Its function is to add a callback function when the state changes for promise instance. As mentioned earlier, the first parameter of the then method is the callback function in the resolved state, and the second parameter (optional) is the callback function in the rejected state.
The then method returns a new Promise instance (note that it is not the original Promise instance). Therefore, you can use chain writing, that is, the then method can be called later by another then method.

getJSON("/posts.json").then(function(json) {
  return json.post;
}).then(function(post) {
  // ...
});

The above code uses the then method to specify two callback functions in turn. After the first callback function is completed, the returned result will be passed into the second callback function as a parameter. Using chained then, you can specify a set of callback functions to be called in order. At this time, the previous callback function may return a Promise object (i.e. asynchronous operation). At this time, the latter callback function will wait for the state of the Promise object to change before being called.

getJSON("/post/1.json").then(function(post) {
  return getJSON(post.commentURL);
}).then(function (comments) {
  console.log("resolved: ", comments);
}, function (err){
  console.log("rejected: ", err);
});

In the above code, the callback function specified by the first then method returns another Promise object. At this time, the callback function specified by the second then method will wait for the state of the new Promise object to change. If the status changes to resolved, the first callback function will be called. If the status changes to rejected, the second callback function will be called. If the arrow function is used, the above code can be written more succinctly.

getJSON("/post/1.json").then(
  post => getJSON(post.commentURL)
).then(
  comments => console.log("resolved: ", comments),
  err => console.log("rejected: ", err)
);

4. How to use Promise.all

The Promise.all() method is used to wrap multiple Promise instances into a new Promise instance.

const p = Promise.all([p1, p2, p3]);

In the above code, the Promise.all() method accepts an array as a parameter. p1, p2 and p3 are Promise instances. If not, it will call the Promise.resolve method mentioned below to convert the parameter into a Promise instance for further processing. In addition, the parameter of Promise.all() method can not be an array, but it must have an Iterator interface, and each member returned is a Promise instance.

The state of p is determined by p1, p2 and p3, which can be divided into two cases.

  1. Only when the states of p1, p2 and p3 become fully, the state of p will become fully. At this time, the return values of p1, p2 and p3 form an array and are passed to the callback function of p.
  2. As long as one of p1, p2 and p3 is rejected, the status of p becomes rejected. At this time, the return value of the first rejected instance will be passed to p's callback function.

Here is a specific example.

// Generate an array of Promise objects
const promises = [2, 3, 5, 7, 11, 13].map(function (id) {
  return getJSON('/post/' + id + ".json");
});

Promise.all(promises).then(function (posts) {
  // ...
}).catch(function(reason){
  // ...
});

In the above code, promises is an array containing six Promise instances. The callback function behind the Promise.all method will be called only when the state of these six instances becomes fully or one of them becomes rejected.

5. How to use Promise.race

The Promise.race() method also packages multiple Promise instances into a new Promise instance.

const p = Promise.race([p1, p2, p3]);

In the above code, as long as one instance of p1, p2 and p3 changes the state first, the state of p will change accordingly. The return value of the Promise instance that changed first is passed to the callback function of p.

The parameters of Promise.race() method are the same as those of Promise.all() method. If it is not a Promise instance, the Promise.resolve() method mentioned below will be called first to convert the parameters into a Promise instance, and then further processing.

The following is an example. If no result is obtained within the specified time, the Promise state will be changed to reject, otherwise it will be changed to resolve.

const p = Promise.race([
  fetch('/resource-that-may-take-a-while'),
  new Promise(function (resolve, reject) {
    setTimeout(() => reject(new Error('request timeout')), 5000)
  })
]);

p
.then(console.log)
.catch(console.error);

In the above code, if the fetch method cannot return results within 5 seconds, the state of variable p will change to rejected, thus triggering the callback function specified by the catch method.

Tags: Front-end

Posted on Thu, 23 Sep 2021 06:01:04 -0400 by voitek