JavaScript Promise

160 阅读4分钟

1.概要

  • Promise是ES6提供的类,目的是更加优雅地书写复杂的异步编程
  • Promise支持地浏览器情况:Chrome 58/Edge 14/Firefox 54/Safari 10/Opera 55

2.构造Promise

new Promise(function (resolve,reject){
    //要做的事情...
})

3.Promise的优势如以下代码:

//此程序使用“函数瀑布”来实现的,可想而知,在一个复杂的程序中,用“函数瀑布”实现的程序
//无论是维护还是异常处理都是一件特别繁琐的事情,而且会让缩进格式变得非常冗赘
setTimeout(function(){
    console.log('first');
    setTimeout(function(){
        console.log('second');
        setTimeout(function(){
            console.log('third');
        },3000);
    },4000);
},1000);
//下面是用Promise来实现同样的功能
new Promise(function(resolve, reject) {
    setTimeout(function() {
        console.log('first');
        resolve();
    }, 1000)
}).then(function() {
    return new Promise(function(resolve, reject) {
        setTimeout(function() {
            console.log('second');
            resolve();
        }, 4000)
    }).then(function() {
        setTimeout(function() {
            console.log('third');
        }, 3000)
    })
})
//对上述Promise函数进行简化
function print(delay, message) {
    return new Promise(function (resolve, reject) {
        setTimeout(function () {
            console.log(message);
            resolve();
        }, delay);
    });
}
print(1000, "first").then(function () {
    return print(4000, "second");
}).then(function () {
    print(3000, "third");
});

4.Promise的构造函数

  • Promise构造函数是JS中用于创建Promise对象的内置构造函数
  • Promise构造函数接受一个函数作为参数,该函数是同步的并且会被立即执行,所以我们称为起始函数。起始函数包括两个参数resolve(成功状态)和reject(失败状态),当起始函数执行成功时,resolve函数被调用并传递成功的结果。若起始函数执行失败,reject函数被调用并传递失败的原因。
  • Promise构造函数返回一个Promise对象,该对象具有以下几个方法:
  • then:用于处理Promise成功状态的回调函数
    
  • catch:用于处理Promise失败状态的回调函数
    
  • finally:无论Promise是成功还是失败,都会执行的回调函数
    
const promise = new Promise((resolve, reject) => {//创建Promise对象
    // 异步操作
    setTimeout(() => {
      if (Math.random() < 0.5) {
        resolve('success');//成功
      } else {
        reject('error');//失败
      }
    }, 1000);
  });
   
  promise.then(result => {//then方法处理Promise成功的回调
    console.log(result);
  }).catch(error => {//catch方法处理Promise失败的回调
    console.log(error);
  });
new Promise(function (resolve, reject) {
    var a = 0;
    var b = 1;
    if (b == 0) reject("Divide zero");
    else resolve(a / b);
}).then(function (value) {
    console.log("a / b = " + value);
}).catch(function (err) {
    console.log(err);
}).finally(function () {
    console.log("End");
});
//执行结果:
//a/b=0
//End

Promise 类有 .then() .catch() 和 .finally() 三个方法,这三个方法的参数都是一个函数,.then() 可以将参数中的函数添加到当前 Promise 的正常执行序列,.catch() 则是设定 Promise 的异常处理序列,.finally() 是在 Promise 执行的最后一定会执行的序列。 .then() 传入的函数会按顺序依次执行,有任何异常都会直接跳到 catch 序列。

5.相关例子理解

let promise = new Promise(function(resolve, reject) {
    //To Do 要异步执行的事情,这个异步执行的事情有可能成功执行完毕,那么Promise将是fulfilled状态,如果执行失败则是rejected;
    //下面测试代码,人为设置为rejected状态;
    reject("将当前构建的Promise对象的状态由pending(进行中)设置为rejected(已拒绝)"); //当然此处也可以设置为fulfilled(已完成)状态
})

promise.then( //调用第一个then()
    success => {
        console.log("异步执行成功,状态为:fulfilled,成功后返回的结果是:" + success);
        return (" 当前 success ");
    },
    error => {
        console.log("异步执行失败,状态为rejected,失败后返回的结果是:" + error);
        return (" 当前 error ");
    }
).then(
    //调用第二个then() 因为调用第一个then()方法返回的是一个新的promise对象,此对象的状态由上面的success或者error两个回调函数的执行情况决定的:
    //如果回调函数能正常执行完毕,则新的promise对象的状态为fulfilled,下面执行success2,如果回调函数无法正常执行,则promise状态为rejected;下面执行error2
    success2 => {
        console.log("第一个then的回调函数执行成功 成功返回结果:" + success2);
        throw (" 当前 success2 "); //自定义异常抛出
    },
    error2 => {
        console.log("第一个then的回调函数执行失败 失败返回结果:" + error2);
        return (" 当前 error2 ");
    }
).catch(err => {
    //当success2或者error2执行报错时,catch会捕获异常;
    console.log("捕获异常:" + err);
});

//上述代码,打印如下:
//异步执行失败,状态为rejected,失败后返回的结果是:将当前构建的Promise对象的状态由pending(进行中)设置为rejected(已拒绝)
//第一个then的回调函数执行成功 成功返回结果: 当前 error
//捕获异常: 当前 success2