Promise 必须为以下三种状态之一:等待态(Pending)、执行态(Fulfilled)和拒绝态(Rejected)。一旦Promise 被 resolve 或 reject,不能再迁移至其他任何状态(即状态 immutable)。
基本过程:
- 初始化 Promise 状态(pending)
- 立即执行 Promise 中传入的 fn 函数,将Promise 内部 resolve、reject 函数作为参数传递给 fn ,按事件机制时机处理
- 执行 then(..) 注册回调处理数组(then 方法可被同一个 promise 调用多次)
- Promise里的关键是要保证,then方法传入的参数 onFulfilled 和 onRejected,必须在then方法被调用的那一轮事件循环之后的新执行栈中执行。
真正的链式Promise是指在当前promise达到fulfilled状态后,即开始进行下一个promise.
用自定义的函数模拟出Promise的链式调用
new Promise((resolve, reject) => {
resolve({ test: 1 });
})
.then((data) => {
console.log("result1", data);
return "then后面的then";
})
.then((res) => {
console.log(res);
});
new Promise((resolve, reject) => {
resolve({ test: 333 });
}).then((res) => {
console.log(res);
});
//result1 { test: 1 }
//result3
const l1 = new lszPromise((resolve, reject) => {
resolve({ test: 1 });
})
.then((data) => {
console.log("lxm1", data);
return "lszPromise then后面的then";
})
.then((res) => {
console.log(res);
});
new lszPromise((resolve, reject) => {
resolve({ test: 333 });
}).then((res) => {
console.log("lxm", res);
});
// 仿 promise函数
function lszPromise(fn) {
let state = "pending"; // 状态标识, fulfilled, rejected
let data = null;
const callbackList = []; // 回调d对象队列
fn(resolve, reject);
function resolve(value) {
// 因为是异步任务,所以需要使用setTimeout来模拟异步
// 没有写异步函数,promise将是同步执行
setTimeout(() => {
if (state !== "pending") return; // 状态只能更改一次,所以改变之后不能执行
state = "fulfilled";
data = value;
// 执行回调函数
doCallBack();
}, 0);
}
function reject(err) {
setTimeout(() => {
if (state !== "pending") return; // 状态只能更改一次,所以改变之后不能执行
state = "rejected";
data = err;
// 执行回调函数
doCallBack();
}, 0);
}
function doCallBack() {
// 执行回调队列中的函数
while (callbackList.length) {
// 获取队列首位
const successFn = callbackList.shift();
handle(successFn);
}
}
// handle接收一个对象 onFulfilled回调函数, resolve函数
function handle(callback) {
if (state === "pending") {
callbackList.push(callback);
return;
}
if (state === "fulfilled") {
if (!callback.onFulfilled) {
callback.resolve(data);
return;
}
const res = callback.onFulfilled(data);
callback.resolve(res);
}
}
this.then = function (onFulfilled) {
return new lszPromise((resolve, reject) => {
handle({
onFulfilled,
resolve,
});
});
};
}