原文地址: https://www.jeremyjone.com/771/ ,转载请注明。
有了前文的基础,我们深入剖析一下 Promise 的原理。
Promise
由于 JS 的单线程和任务队列,造成了很多函数嵌套,当这种嵌套激增,就会造成所谓的 回调地狱
,这是我们深恶痛绝的。
创建一个 Promise
基于几方面原因,JS 催生了 Promise
,它解决了很多问题。先看用法:
new Promise(
(
resolve, // 成功状态回调
reject // 失败状态回调
) => {
// 执行体
}
);
这是一个最基本的创建一个 Promise 的方式。
Promise 的状态
Promise 官方定义了三种状态:
- pending:准备阶段
- fulfilled:完成,可以理解为成功
- rejected:失败,理解为失败
当一个 Promise 被创建之后,它的状态是 pending
,此时会执行 执行体
的内容。
当遇到回调时:
resolve
会将 Promise 的状态改为成功(fulfilled)reject
会将 Promise 的状态改为失败(rejected)
resolve()
和 reject()
在同一执行体时,只有第一个会被执行。
new Promise((resolve, reject) => {
// ... 执行逻辑
resolve("succeed");
});
可能有些人会有疑问了,好像还见过 resolved
状态。这里解释一下,它不是标准状态。总的来说,一个 Promise 被创建之后,一定是 pending
,之后无论执行了 resolve()
还是 reject()
,状态都属于 resolved
,它表示已处理,不会再改变的状态。所以,fulfilled
与 rejected
都属于 resolved
的一种状态。
总结如下:
pending -> resolve() -> fulfilled -> resolved
pending -> reject() -> rejected -> resolved
只有当改变 Promise 状态的时候,才会创建微任务,也就是只有当执行到 resolve()
或 reject()
时,才会有微任务生成。
Promise 状态的中转
resolve()
和 reject()
方法如果返回一个值,它会按照上面的逻辑改变状态。但是返回的是一个 Promise 呢?此时它将返回该 Promise 的状态,而与自身无关。
const p1 = new Promise((resolve, reject) => {
reject("failed");
});
new Promise((resolve, reject) => {
resolve(p1); // 虽然我们调用的是成功回调,但是它返回的是 p1 的失败状态
}).then(
val => console.log("val: " + val),
err => console.log("err: " + err)
);
此时,其打印的应该是:
err: failed;
使用 then 处理 Promise 的返回状态
上面已经创建了一个 Promise,回调时需要通过 then
方法。
它接收两个参数,一个成功,一个失败。
console.log("start");
let promise = new Promise((resolve, reject) => {
console.log("promise");
resolve("succeed");
}).then(
val => console.log("val: " + val),
err => console.log("err: " + err)