3

What is Promise

Promise is a solution for asynchronous programming. Promise object has been provided in ES6. A Promise object will be in the following states (fulfilled and rejected will not change once confirmed):

  • Pending: The initial state, neither being honored nor rejected.
  • Fulfilled: means the operation completed successfully.
  • Rejected: means the operation failed.

Basic usage

Promise object is a constructor to create Promise instance of 06177caa3e283c, which receives two parameters resolve and reject .

  • resolve action is to Promise state object from pending becomes fulfilled , upon successful call asynchronous operation, and the result of the asynchronous operation, to pass out as a parameter.
  • reject action is to Promise state object from pending becomes rejected , invoked when an asynchronous operation fails, and the asynchronous operation errors may be, as a parameter to pass out.
const promise = new Promise(function(resolve, reject) {
  // ... 
  if (/* 异步操作成功 */){
    resolve(value);
  } else {
    reject(error);
  }
});

Promise instance is generated, use the then method to specify the callback functions fulfilled state and the rejected

  • then receives two parameters. The first is Promise object changes to fulfilled , and the second is the callback function when the rejected
  • catch receives the callback function when the state of the Promise rejected
promise.then(function (value){
    // ....
},function (err){
    // .... err
})
  
promise.then(function (value){
    // ....
}).catch(function (err){
    // ....
})

Promise method

Promise.prototype.then()

then method is defined on the prototype object Promise.prototype . As mentioned earlier, it receives two optional parameters. The first parameter is fulfilled state, and the second parameter is the callback function rejected

then method returns a new Promise , which is convenient for us to use chain writing. For example, then followed by then . When the first callback function is completed, the return result will be used as a parameter and passed to the second callback function. This chaining method can easily specify a set of callback functions to be called in order.

loadData().then(function (value){
    return 3
}).then(function (num){
    console.log("ok", num) // 3
})

Promise.prototype.catch()

catch method is used to specify the callback function when an error occurs. If an asynchronous operation throws an error, the status will change to rejected , and the callback function specified by the catch() method will be called to handle the error.

const promise = new Promise(function(resolve, reject) {
  throw new Error('unkonw error'); // 抛出错误状态变为 -> reject
});
const promise = new Promise(function(resolve, reject) {
  reject('unkonw error') // 使用reject()方法将状态变为 -> reject
});
promise.catch(function(error) {
  console.log(error);
});

Promise object will be passed backwards until it is caught. For example, the following code: catch will capture the errors thrown in loadData and two then

loadData().then(function(value) {
  return loadData(value);
}).then(function(users) {
 
}).catch(function(err) {
  // 处理前面三个Promise产生的错误
});

If we do not set catch() , when an error is encountered, Promise will not throw the error outside, that is, it will not affect the execution of external code.

const promise = new Promise(function(resolve, reject) {
      resolve(a) // ReferenceError: a is not defined
});
promise.then(function(value) {
  console.log('value is ', value)
});
setTimeout(() => { console.log('code is run') }, 1000); // code is run

Promise.prototype.finally()

finally() method will perform operations regardless of the final state of the Promise object. The following is a general structure we use Promise.

promise
.then(result => {···})
.catch(error => {···})
.finally(() => {···});

Promise.all()

Promise.all() method can wrap multiple Promise instances into a new Promise instance and return.

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

The new promise state depends on the "incoming promise ".

  • Only when the state of all "incoming promise " becomes fulfilled , its state will become fulfilled . At this time, the promise " forms an array and is passed to the callback function of promise
  • If one of the "incoming promise " is rejected , the status of the promise rejected , and the first reject from promise will be passed to the callback function of promise
const promises = [1,2,3,4].map(function (id) {
  return loadData(id);
});

Promise.all(promises).then(function (users) {
  // ...
}).catch(function(err){
  // ...
});

Promise.race()

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

Promise.race() method parameters and Promise.all() method for the same.

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

Promise.all() and Promise.race() :

  • Promise.all() , if all are executed successfully, all successful promise values are returned, and if there is a failure, the first failed value is returned.
  • Promise.race() , returns the promise that has been executed first, which may be fulfilled or rejected.

The usage scenarios of these two methods.

Scenario 1 , after the user logs in to the homepage of the social networking site, it will asynchronously request to pull user information, watch list, and fan list at the same time. We need to ensure that all data requests are successful before rendering the page. As long as one piece of data is unsuccessful, the page will be redirected. Promise.all can be used here.

function initUserHome() {
  Promise.all([
  new Promise(getMe),
  new Promise(getFollows),
  new Promise(getFans)
])  
    .then(function(data){
        // 显示页面
  })
    .catch(function(err){
    // .... 重定向页面
  });
};

initUserHome();

scenario two , if we are doing a ticket grabbing software, although we have requested a lot of ticket sales channels, we only need to return to the first Promise that has been Promise.race .

function getTicket() {
  Promise.race([
  new Promise(postASell),
  new Promise(postBSell),
  new Promise(postCSell)
])  
    .then(function(data){
        // 抢票成功
  })
    .catch(function(err){
    // .... 抢票失败,重试
  });
};

getTicket();

Promise.allSettled()

When using Promise.all() , if one Promise fails, the other Promise will not stop execution.

const requests = [
  fetch('/url1'),
  fetch('/url2'),
  fetch('/url3'),
];

try {
  await Promise.all(requests);
  console.log('所有请求都成功。');
} catch {
  console.log('有一个请求失败,其他请求可能还没结束。');
}

Sometimes, we want to wait until a set of asynchronous operations are over before proceeding to the next step. At this time, you need to use Promise.allSettled() , its parameter is an array, each member of the array is a Promise object, and a new Promise object is returned. It only waits until all the Promise objects in the parameter array have changed their state (whether it is fulfilled or rejected ) before the returned Promise object changes state.

const requests = [
  fetch('/url1'),
  fetch('/url2'),
  fetch('/url3'),
];

await Promise.allSettled(requests);
console.log('所有请求完成后(包括成功失败)执行');

Promise.any()

As long as one of the incoming Promise becomes the fulfilled state, the new Promise will become the fulfilled state; if all the incoming Promise become the rejected state, the new Promise will become the rejected state.

Promise.any() and Promise.race() similar, except that Promise.any() not because of a Promise become rejected state ends, must wait until all parameters Promise become rejected state will end.

Promise.race() back to the 06177caa3e2e80 multi-channel ticket grabbing scenario, if we need to ensure that either one channel succeeds in grabbing tickets, or all channels fail, it is more appropriate to Promise.any()

function getTicket() {
  Promise.any([
  new Promise(postASell),
  new Promise(postBSell),
  new Promise(postCSell)
])  
    .then(function(data){
        // 有一个抢票成功
  })
    .catch(function(err){
    // .... 所有渠道都失败了
  });
};

getTicket();

Promise.resolve()

Promise.resolve() method converts an existing object into a Promise object. It is equivalent to the following code:

new Promise(resolve => resolve(1))

The incoming parameters are different, deal with

  1. Parameter Promise instance, it will return to this instance without any modification.
  2. Parameter thenable object, it will turn this object into Promise object, and then immediately execute the then() method of thenable

    let thenable = {
      then: function(resolve, reject) {
        resolve(1);
      }
    };
  3. The parameter is a normal value, and a new Promise object is returned with a status of resolved .

    const promise = Promise.resolve(1);
    
    promise.then(function (value) {
      console.log(value) // 1
    });
  4. Without parameters, directly return a Promise object in resolved

Promise.reject()

Promise.reject(reason) method will also return a new Promise instance whose status is rejected .

const promise = Promise.reject('unkonw error');
// 相当于
const promise = new Promise((resolve, reject) => reject('unkonw error'))

promise.then(null, function (s) {
  console.log(s)
});
// unkonw error

Simple scene

Load pictures asynchronously:

function loadImageAsync(url) {
  return new Promise(function(resolve, reject) {
      const image = new Image();
    image.onload  = resolve;
    image.onerror = reject;
    image.src = url;
  });
}

Request timeout processing:

//请求
function request(){
    return new Promise(function(resolve, reject){
          // code ....
         resolve('request ok')
    })
}

function timeoutHandle(time){
         return new Promise(function(resolve, reject){
        setTimeout(function(){
            reject('timeout');
        }, time);
    });
}

Promise.race([
    request(),
    timeoutHandle(5000)
])
.then(res=>{
    console.log(res)
}).catch(err=>{
    console.log(err)// timeout
})

summary

This article summarizes the Promise , welcome to leave a message.


编程码农
455 声望1.4k 粉丝

多年编程老菜鸟👨‍💻🦍