Promise

用于表示一个异步操作的最终完成 (或失败)及其结果值。

状态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function test(resolve, reject) {
var timeOut = Math.random() * 2;
console.log('pending...')
setTimeout(function () {
if (timeOut < 1) {
// fulfilled
console.log('call resolve()...');
resolve('200 OK');
}
else {
// rejected
console.log('call reject()...');
reject('400 error');
}
}, 0);
}

  • 待定(pending): 初始状态,既没有被兑现,也没有被拒绝。

    1
    var pending = new Promise(test); // pending...
  • 已兑现(fulfilled): 意味着操作成功完成。

    1
    pending.then((res)=>{console.log(res)}); // 200 OK
  • 已拒绝(rejected): 意味着操作失败。

    1
    pending.catch((res)=>{console.log(res)}); // 400 error

事实上我们在.then()函数里面,如果抛出错误也会进入.catch()函数里面,这是因为Promise.prototype.thenPromise.prototype.catch方法返回的是Promise对象。

1
pending.then((res)=>{throw 'error'}); // 会进入p1.catch()里面

.catch()也抛出错误那么就会触发unhandledrejection事件(在下面有所介绍)。

1
pending.catch((res)=>{throw 'error'})

有一点你需要注意因为JavaScript是单线程,所以.then().catch()会在当前作用域执行完后执行。

1
2
3
4
pending
.then(function (res) {console.log(res)})
.catch(function (res) {console.log(res)});
console.log('start...');

监听拒绝(reject)事件

当 Promise 被拒绝时,会触发rejectionhandledunhandledrejection事件并被派发到全局作用域。

  • rejectionhandled

    当 Promise 被拒绝、并且在 reject 函数处理该 rejection 之后会派发此事件。

  • unhandledrejection

    当 Promise 被拒绝,但没有提供 reject 函数来处理该 rejection 时,会派发此事件。

通过window.addEventListener监听Promise拒绝事件。这个事件有两个属性,一个是promise属性,该属性指向被驳回的Promise;另一个是reason属性,该属性用来说明Promise被驳回的原因。

1
2
3
window.addEventListener("unhandledrejection", (event)=>{
console.log(event.promise, event.reason, event);
})

链式调用

连续执行两个或者多个异步操作是一个常见的需求,在上一个操作执行成功之后,开始下一个的操作,并带着上一步操作所返回的结果。我们可以通过创造一个Promise链来实现这种需求。

1
[func1, func2, func3].reduce((p, f) => p.then(f), Promise.resolve())

await

用于等待一个Promise对象。

只能在异步函数(async function)中使用。

  • 若Promise正常处理(fulfilled),其回调的resolve函数参数作为await表达式的值,继续执行async function

  • 若Promise处理异常(rejected),await 表达式会把Promise的异常原因抛出。

  • 若await操作符后的表达式的值不是一个Promise,则返回该值本身。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
(async function () {
function test(resolve, reject) {
var timeOut = Math.random() * 2;
console.log('pending...')
setTimeout(function () {
if (timeOut < 1) {
// fulfilled
console.log('call resolve()...');
resolve('200 OK');
}
else {
// rejected
console.log('call reject()...');
reject('400 error');
}
}, 0);
}
window.addEventListener("unhandledrejection", event => {
console.log('unhandledrejection', event.promise, event.reason, event);
})
var pending = await new Promise(test)
.then(function (res) { console.log(res) })
.catch(function (res) { console.log(res) });
// 等待pending运行完 在运行下面代码
console.log('start...');
})()

Promise - JavaScript | MDN (mozilla.org)

await - JavaScript | MDN (mozilla.org)