乐趣区

ES6-Promise-Promise的执行顺序和异步性

在前面的 ES6 Promise 系列文章的第一篇和第二篇分别介绍了如何创建动态的 Promise 和已完成态的 Promise。但是前面 2 篇里面的所有示例都相对简单,没有涉及到链式调用。

我们知道 Promise 用来处理异步操作,异步操作的执行顺序是相对比较复杂的,如果再涉及到链式调用,则情况会变得更复杂。这篇文章会通过一个相对简单的代码示例来让大家对 Promise 的执行顺序和异步性有正确的理解,从而可以以此类推处理更复杂的情况。

我们先看代码:

let a = Promise.reject('a').then(() => {console.log('a passed')
}).catch(() => {console.log('a failed')
});

Promise.reject('b').catch(() => {console.log('b failed');
}).then(() => {console.log('b passed');
});

以上代码的打印顺序依次是什么呢?可以先自己思考一下。正确的答案是:

b failed
a failed
b passed

如果你的答案是错误的,那就请继续看接下来的分析。对于 Promise 的链式调用,我建议可以按照下面的步骤去分析代码,这样非常有利于理解:

1: 拆分成非链式调用
2: 排序出正确的 job queue

现在我们就来实际应用以下:
1: 拆分成非链式调用

let pa = Promise.reject('a').then(() => {console.log('a passed');
});
let pa1 = pa.catch(() => {console.log('a failed');
});

let pb = Promise.reject('b').catch(() => {console.log('b failed');
});
let pb1 = pb.then(() => {console.log('b passed');
});

这一步需要大家理解的一点是:then()和 catch()都是返回一个 Promise,而且是不同于母 Promise 的一个新的,完全独立的 Promise。这也是 Promise 可以链式调用的基础。

2: 排序出正确的 job queue

// 一级 Promise
let pa = Promise.reject('a').then(() => {console.log('a passed');
});
let pb = Promise.reject('b').catch(() => {console.log('b failed');
});

// 二级 Promise
let pa1 = pa.catch(() => {console.log('a failed');
});
let pb1 = pb.then(() => {console.log('b passed');
});

给 Promise 的 job queue 排序遵循 2 个原则

1: 一级 Promise 为一轮,排在前面,依次类推
2: 同一级的 Promise 根据代码定义顺序决定先后顺序

根据上面的 2 个原则,
1: 我们首先识别出 pa 和 pb 为一级 Promise,它们俩肯定是在 pa1 和 pb1 前面的。
2: 在同一级里面,根据代码定义顺序,pa 在 pb 前面;pa1 在 pb1 之前
排除了正确的 job queue 之后,我们再俩看代码的执行结果:
1: pa 因为是一个 reject 状态的 Promise,但是它只定义了 fulfilled 状态的处理函数,没有定义 rejected 状态的处理函数。根据我们 Promise 系列第二篇的知识,我们知道 ’a passed’ 永远不会被打印出来。
2: 后面的三个 Promise 就可以按照 job queue 的顺序执行,所以最终我们得到了前面看到的正确打印结果:

b failed
a failed
b passed

以上就是本篇文章的内容。

退出移动版