Promise [all, race, allSettled, any] compare





Promise to define

Promise is a solution to asynchronous programming that makes more sense and is more powerful than traditional solutions — callback functions and events. It was first proposed and implemented by the community, and ES6 has written it into the language standard, unifying usage, and providing Promise objects natively.

A Promise is simply a container that holds the result of an event (usually an asynchronous operation) that will end in the future. Syntactically, a Promise is an object from which to get messages for asynchronous operations. Promise provides a uniform API, and all kinds of asynchronous operations can be handled in the same way.

The characteristics of

The status of an object is unaffected by external influences

  • Pending: Pending
  • Fullfilled: Succeeded
  • Rejected: It has failed

Only the result of an asynchronous operation can determine which state it is in, and no other operation can change that state. Once the state changes, it doesn’t change, and all you get at any time is a change in the state of the Promise object. There are only two possibilities:

  • Change from Pending to depressing
  • Change from Pending to Rejected

As long as these two things are happening the state is fixed, it’s not going to change, it’s going to stay the same and that’s called resolved. If the change has already occurred, you can add a callback to the Promise object and get the same result immediately.

disadvantages

  • First, there is no way to cancel a Promise; once it is created, it is executed immediately and cannot be cancelled halfway through.
  • Second, if you don’t set a callback function, errors thrown inside a Promise won’t be reflected externally.
  • Third, when in a pending state, there is no way to know what stage of progress is currently being made (just started or nearly completed)


Basic usage

const promise = new Promise(function(resolve, reject) {
  if (true){
    resolve(2);
  } else {
    reject(3); }}); promise.then((value) = > {
	console.log(value)
}, (err) = > {
	console.log(err)
})
Copy the code
  • The Promise constructor takes a function as an argument, resolve and reject. They are two functions that are provided by the JavaScript engine and do not need to be deployed themselves.
  • The resolve function changes the state of the Promise object from “unfinished” to “successful.” It will be called when the asynchronous operation succeeds and will pass the result of the asynchronous operation as an argument. The Reject function changes the state of the Promise object from “unfinished” to “failed” (i.e., from Pending to Rejected). It is called when the asynchronous operation fails and passes the error reported by the asynchronous operation as a parameter.


Examples of simulated Ajax operations

const getJSON = function(url) {
  const promise = new Promise(function(resolve, reject){
    const handler = function() {
      if (this.readyState ! = =4) {
        return;
      }
      if (this.status === 200) {
        resolve(this.response);
      } else {
        reject(new Error(this.statusText)); }};const client = new XMLHttpRequest();
    client.open("GET", url);
    client.onreadystatechange = handler;
    client.responseType = "json";
    client.setRequestHeader("Accept"."application/json");
    client.send();

  });

  return promise;
};

getJSON("/posts.json").then(function(json) {
  console.log('Contents: ' + json);
}, function(error) {
  console.error('Wrong', error);
});
Copy the code

Resolve and reject do not terminate the Promise function execution

new Promise((resolve, reject) = > {
  resolve(1);
  console.log(2);
}).then(r= > {
  console.log(r);
});

/ / 2
/ / 1
Copy the code

The concept here is clear: the Promise argument function executes values synchronously, whereas the then execution is asynchronous.


Promise.prototype.catch

let promise = new Promise(function(resolve, reject) {
  if (false) {throw new Error(123);
    resolve(2);
  } else {
    reject(3); }}); promise.then((value) = > {
	console.log(value)
}, (err) = > {
	console.log(err)  / / output error
})

promise.then((value) = > {
	console.log(value)
}).catch((err) = > {
	console.log(err)  / / output error
})
Copy the code

The above code is equivalent, promise.prototype.catch () is an alias for.then(null, Rejection) or.then(undefined, Rejection) to specify the callback when an error occurs.

Catch can be used as a callback to reject or to catch errors in the reolve function. However, before resolve, the capture is not done if the following is the case.

let promise = new Promise(function(resolve, reject) {
  if (true){
    resolve(2);
    throw new Error(123);
  } else {
    reject(3); }}); promise.then((value) = > {
	console.log(value)
}).catch((err) = > {
	console.log(err)  / / output error
})
Copy the code

It is always recommended that a catch() method be followed by a Promise object to handle errors that occur within a Promise. The catch() method still returns a Promise object, so you can call the then() method later.


Promise.prototype.finally

The finally() method is used to specify actions that will be performed regardless of the final state of the Promise object. This method was introduced as a standard in ES2018.

promise
.then(result= >{...}). The catch (error= >{...}). Finally,() = > {···});
Copy the code

The callback function of the finally method accepts no parameters, which means there is no way to know whether the Promise state is fulfilled or rejected. This suggests that operations in the finally method should be state independent and not depend on the result of a Promise’s execution.

let promise = new Promise(function(resolve, reject) {
  if (true){
    resolve(2);
  } else {
    reject(3); }}); promise.then((value) = > {
	console.log(value)
}).catch((err) = > {
	console.log(err)  / / output error
}).finally(() = > {
	console.log('over')})Copy the code


promise.all

Promise.all is used to pack multiple Promise examples into a new Promise instance.

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

The promise.all () method takes an array of arguments. P1, p2, and p3 are all Promise instances. If they are not, the Promise. In addition, the promise.all () method can take arguments that are not arrays, but must have an Iterator interface and return each member as 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 depressing, the state of P will become depressing. At this time, the return values of P1, P2 and P3 will form an array and be passed to the callback function of P.
  2. If p1, P2, and P3 are rejected, P becomes rejected, and the return value of the first rejected instance is passed to p’s callback function.


const p1 = new Promise((resolve, reject) = > {
  resolve('hello');
})
.then(result= > result)
.catch(e= > e);

const p2 = new Promise((resolve, reject) = > {
  throw new Error('Error reported');
})
.then(result= > result)
.catch(e= > e);

Promise.all([p1, p2])
.then(result= > console.log(result))
.catch(e= > console.log(e));
Copy the code

const p1 = new Promise((resolve, reject) = > {
  resolve('hello');
})
.then(result= > result)
.catch(e= > e);

const p2 = new Promise((resolve, reject) = > {
  throw new Error('Error reported');
})
.then(result= > result)

Promise.all([p1, p2])
.then(result= > console.log(result))
.catch(e= > console.log(e));
Copy the code





P1 will be resolved, P2 will first try, but P2 has its own catch method which returns a new Promise instance that P2 actually points to. This instance will also become Resolved after executing the catch method, causing both instances in promise.all () to call the then callback and not the catch callback.

If P2 does not have its own catch method, the catch method of promise.all () is called.

Question:

Modify the above code so that P2’s catch executes and Promise’s catch executes.

const p1 = new Promise((resolve, reject) = > {
  resolve('hello');
})
.then(result= > result)
.catch(e= > e);

const p2 = new Promise((resolve, reject) = > {
  throw new Error('Error reported');
})

p2.then(result= > result)
.catch(e= > e);

Promise.all([p1, p2])
.then(result= > console.log(result))
.catch(e= > console.log(e));
Copy the code





The two types of code execute in a different order.

  • P2 -> Promise.all -> P2.then
  • P2 -> P2.then -> Promise.all


Promise.race

The promise.race () method again wraps multiple Promise instances into a new Promise instance.

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

If one instance of P1, P2, and P3 changes state first, then the state of P changes. The return value of the first changed Promise instance is passed to p’s callback. The parameters of the promise.race () method are the same as those of the promise.all () method. If it is not a Promise instance, the promise.resolve () method, described below, is first called to turn the parameters into a Promise instance, and then further processing.

const p1 = new Promise((resolve, reject) = > {
  setTimeout(() = > {
    resolve('p1');
  }, 1000)})const p2 = new Promise((resolve, reject) = > {
  setTimeout(() = > {
    reject('p2');
  }, 500)})const p = Promise.race([p1, p2]).then(result= > {
  console.log(result)
}).catch(err= > {
  console.log(err);
});
Copy the code


Promise.allSettled

The promise.allSettled () method takes a set of Promise instances as parameters and wraps them into a new Promise instance. The wrapper instance will not complete until all of these parameter instances return the result, whether this is fulfilled or Rejected. This method was introduced by ES2020.

const p1 = new Promise((resolve, reject) = > {
  setTimeout(() = > {
    reject('p1');
  }, 1000)})const p2 = new Promise((resolve, reject) = > {
  setTimeout(() = > {
    reject('p2');
  }, 500)})const p = Promise.allSettled([p1, p2]).then(result= > {
  console.log(result)
}).catch(err= > {
  console.log(err);
});
Copy the code

Each object has a status attribute, whose value can only be the string fulfilled or the string Rejected. Someday, the object has the value attribute, and the object has the reason attribute, which corresponds to the return values of the two states.


Promise.any

ES2021 introduces the promise.any () method. The method takes a set of Promise instances as parameters and returns them wrapped as a new Promise instance. As long as one parameter instance becomes a depressing state, the packaging instance will become a depressing state. If all parameter instances become the Rejected state, the wrapper instance becomes the Rejected state.

Promise.any(promises).then(
  (first) = > {
    // Any of the promises was fulfilled.
  },
  (error) = > {
    // All of the promises were rejected.});Copy the code
const p1 = new Promise((resolve, reject) = > {
  setTimeout(() = > {
    reject('p1');
  }, 1000)})const p2 = new Promise((resolve, reject) = > {
  setTimeout(() = > {
    reject('p2');
  }, 500)})const p = Promise.any([p1, p2]).then(result= > {
  console.log(result)
}).catch(err= > {
  console.log(err);
});
Copy the code




Promise.resolve

Sometimes you need to turn an existing object into a Promise object, and the promise.resolve () method does this.

Promise.resolve('foo')
/ / equivalent to the
new Promise(resolve= > resolve('foo'))
Copy the code


Resolve Four parameters

The parameter is a Promise instance. If the parameter is a Promise instance, promise. resolve returns the instance unchanged.

The argument is a Thenable object, which is an object with a then method, such as this one

let thenable = {
  then: function(resolve, reject) {
    resolve(42); }};let p1 = Promise.resolve(thenable);
p1.then(function (value) {
  console.log(value);  / / 42
});
Copy the code

The promise.resolve () method turns this object into a Promise object and immediately executes the thenable object’s then() method.

Since the string Hello is not an asynchronous operation, it returns the state of the Promise instance from lifetime achievement to Resolved, so the callback will execute immediately. The arguments to the promise.resolve () method are also passed to the callback function.

const p = Promise.resolve('Hello');
p.then(function (s) {
  console.log(s)
});
Copy the code

The promise.resolve () method allows a call with no arguments to return a Resolved Promise object. So, if you want a Promise object, the convenient way to do this is to call the promise.resolve () method directly.

const p = Promise.resolve();

p.then(function () {
  // ...
});
Copy the code


Promise.reject

The promise.Reject (Reason) method also returns a new Promise instance with a state of Rejected.

const p = Promise.reject('Wrong');
/ / is equivalent to
const p = new Promise((resolve, reject) = > reject('Wrong'))

p.then(null.function (s) {
  console.log(s)
});
/ / make a mistake
Copy the code

With reference to

Es6.ruanyifeng.com/#docs/promi…