定义
Promise是异步编程的一种解决方案。它代表了异步操作的最终完成(或失败)及其结果值。Promise有三种状态:
- Pending: 初始状态,既不是成功,也不是失败状态。
- Fulfilled: 操作成功完成。
- 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方法将会被调用,代码执行结果如下:
如果将抛出错误的语句移至第一个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);
});
执行结果如下:
可以看到后面两个then方法都没有得到执行,这就是异常穿透,失败的Promise会导致后续的then方法都得不到执行。
🍕除了异常穿透可以打断then的链式调用,还可以在onResolved回调函数中返回一个状态为Pending的Promise对象来打断then的链式调用
静态方法
Promise提供了四个静态方法:
-
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状态才会执行该回调 });
-
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 });
-
Promise.resolve(): 返回一个fulfilled状态的Promise。
Promise.resolve('success').then(value => { console.log(value); // success });
-
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会使线程阻塞,上述代码返回结果如下
- 上述代码虽然可以执行,但是await一般只写在async函数内部,这样即使线程阻塞也不会影响主线程,因此永远不要在主线程中直接使用await表达式,否则容易使程序卡死、崩溃。