定义

Promise是异步编程的一种解决方案。它代表了异步操作的最终完成(或失败)及其结果值。Promise有三种状态:

  1. Pending: 初始状态,既不是成功,也不是失败状态。
  2. Fulfilled: 操作成功完成。
  3. Rejected: 操作失败。

一个Promise必须处于以上三种状态之一,且状态变化只能是Pending -> Fulfilled 或者 Pending -> Rejected,状态变化不可逆。

实例化

实例化一个Promise对象的代码如下:

const p1 = new Promise((resolve, reject) => {});

构造函数接收一个executor函数,该函数中有两个形参用于改变Promise的状态,reselove(data:unknow)函数会将Promise实例的状态更改为Fullfilled状态,data为PromiseState的值;reject(data:unknow)函数会将Promise实例的状态变更为Rejected状态data为PromiseState的值。

回调

Promise对象的状态一旦改变,便会调用回调函数,回调函数定义在Promise实例的then()方法中,示例如下:

const p1 = new Promise((resolve, reject) => {
    resolve("OK");
});

p1.then(val => {
    console.log(val)
}, reason => {
    console.warn(reason);
});

then(onResolved,onReject?)函数接收两个回调函数分别在Promise对象状态更改为Fulfilled、Rejected状态时调用,onReject回调函数可省略;then()方法的返回值为一个Promise对象,该Promise对象的状态和值讨论如下:

  • 如果onResolved回调函数被调用且返回值为非Promise对象的值,那么then方法返回的Promise对象状态为Fulfilled,PromiseState的值即为onResolved返回的值。
  • 如果onResolved回调函数被调用且返回值为Promise对象,那么then方法返回的Promise的状态和值由onResolved函数返回的Promise确定
  • 如果onResolved回调函数被调用且抛出错误,那么then方法返回的Promise的状态将变为Rejected,PromiseState的值为抛出的错误的值
  • onRejected回调函数被调用,那么then方法返回的Promise对象的状态为Rejected,PromiseState的值为onRejected函数返回的值

一般不将Rejected状态的回调函数写入then方法中,而是写进catch方法中,catch方法指挥在Promise对象的状态变为Rejected时才会被调用,上述代码可更改如下:

const p1 = new Promise((resolve, reject) => {
    resolve("OK");
});

p1.then(val => {
    console.log(val)
}).catch(reason => {
    console.warn(reason)
});

异常穿透

由于Promise对象的then方法返回值也为Promised对象,因此可以进行链式调用

const p1 = new Promise((resolve, reject) => {
    resolve("OK");
});

p1.then(val => {
    console.log(val);
    return "Success";
}).then(val => {
    console.log(val);
    return "Nice";
}).then(val => {
    console.log(val);
    throw "Error";
}).catch(reason => {
    console.warn(reason);
});

上述代码进行了三次then方法的调用,最后一次then方法抛出了错误,因此返回Promise的状态将变为Rejected,catch方法将会被调用,代码执行结果如下:

image-20230506175038049

如果将抛出错误的语句移至第一个then方法中,会怎么样呢

const p1 = new Promise((resolve, reject) => {
    resolve("OK");
});

p1.then(val => {
    console.log(val);
    throw "Error";  
}).then(val => {
    console.log(val);
    return "Nice";
}).then(val => {
    console.log(val);
    return "Success";
}).catch(reason => {
    console.warn(reason);
});

执行结果如下:

image-20230506175325986

可以看到后面两个then方法都没有得到执行,这就是异常穿透,失败的Promise会导致后续的then方法都得不到执行。

🍕除了异常穿透可以打断then的链式调用,还可以在onResolved回调函数中返回一个状态为Pending的Promise对象来打断then的链式调用

静态方法

Promise提供了四个静态方法:

  1. Promise.all(): 将多个Promise实例包装成一个新的Promise实例。

    const p1 = Promise.resolve('p1');
    const p2 = Promise.resolve('p2');
    const p3 = Promise.resolve('p3');
    
    Promise.all([p1, p2, p3]).then(values => {
      console.log(values); // ['p1', 'p2', 'p3'],只有p1,p2,p3都为Fulfilled状态才会执行该回调
    });
    
  2. Promise.race(): 将多个Promise实例包装成一个新的Promise实例,其结果由第一个状态改变的Promise决定。

    const p1 = Promise.resolve('p1');
    const p2 = Promise.resolve('p2');
    const p3 = Promise.reject('p3');
    
    Promise.race([p1, p2, p3]).then(value => {
      console.log(value); // p1
    }).catch(err => {
      console.log(err);  // p3
    });
    
  3. Promise.resolve(): 返回一个fulfilled状态的Promise。

    Promise.resolve('success').then(value => {
      console.log(value); // success 
    });
    
  4. Promise.reject(): 返回一个rejected状态的Promise。

    Promise.reject('fail').catch(err => {
      console.log(err); // fail
    });
    

async、await语法糖

  • 函数如果被async标记,并不表示该函数为异步函数,async标记的函数表示该函数返回一个Promise对象,Promise的结果由返回值确定,参考then方法

  • await表示等待一个Promise对象变为Resolved状态,await表达式只能返回状态为Resolved的Promise对象的PromiseState的值

    const f1 = async () => {
        let a = 1;
        return new Promise((resolve, reject) => {
            let a = 1;
            setTimeout(() => {
                a++;
                resolve(a);
            }, 1000);
        });
    };
    let p1 = await f1();
    console.log(`p1:${p1}`);
    console.log('end');
    
  • await会使线程阻塞,上述代码返回结果如下

image-20230508110013207

  • 上述代码虽然可以执行,但是await一般只写在async函数内部,这样即使线程阻塞也不会影响主线程,因此永远不要在主线程中直接使用await表达式,否则容易使程序卡死、崩溃。