function Promise(executor) {
this.state = "pending";
this.onFulfilledCallback = [];
this.onRejectedCallback = [];
const self = this;
function resolve(value) {
setTimeout(function () {
if (self.state === "pending") {
self.state = "fulfilled";
self.data = value;
for (let i = 0; i < self.onFulfilledCallback.length; i++) {
self.onFulfilledCallback[i](value);
}
}
});
}
function reject(reason) {
setTimeout(function () {
if (self.state === "pending") {
self.state = "rejected";
self.data = reason;
for (let i = 0; i < self.onRejectedCallback.length; i++) {
self.onRejectedCallback[i](reason);
}
}
});
}
try {
executor(resolve, reject);
} catch (reason) {
reject(reason);
}
}
Promise.prototype.then = function (onFulfilled, onRejected) {
const self = this;
let promise2;
return (promise2 = new Promise(function (resolve, reject) {
if (self.state === "fulfilled") {
setTimeout(function () {
if (typeof onFulfilled === "function") {
try {
const x = onFulfilled(self.data);
promiseResolutionProcedure(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
} else {
resolve(self.data);
}
});
} else if (self.state === "rejected") {
setTimeout(function () {
if (typeof onRejected === "function") {
try {
const x = onRejected(self.data);
promiseResolutionProcedure(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
} else {
reject(self.data);
}
});
} else if (self.state === "pending") {
self.onFulfilledCallback.push(function (promise1Value) {
if (typeof onFulfilled === "function") {
try {
const x = onFulfilled(self.data);
promiseResolutionProcedure(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
} else {
resolve(promise1Value);
}
});
self.onRejectedCallback.push(function (promise1Reason) {
if (typeof onRejected === "function") {
try {
const x = onRejected(self.data);
promiseResolutionProcedure(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
} else {
reject(promise1Reason);
}
});
}
}));
};
function promiseResolutionProcedure(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(new TypeError("Chaining cycle detected for promise"));
}
if (x instanceof Promise) {
if (x.state === "pending") {
x.then(function (value) {
promiseResolutionProcedure(promise2, value, resolve, reject);
}, reject);
} else if (x.state === "fulfilled") {
resolve(x.data);
} else if (x.state === "rejected") {
reject(x.data);
}
return;
}
if (x && (typeof x === "object" || typeof x === "function")) {
let isCalled = false;
try {
let then = x.then;
if (typeof then === "function") {
then.call(
x,
function resolvePromise(y) {
if (isCalled) return;
isCalled = true;
return promiseResolutionProcedure(promise2, y, resolve, reject);
},
function rejectPromise(r) {
if (isCalled) return;
isCalled = true;
return reject(r);
}
);
} else {
resolve(x);
}
} catch (e) {
if (isCalled) return;
isCalled = true;
reject(e);
}
} else {
resolve(x);
}
}
module.exports = Promise;
Promise函数
- 初始化状态(state)为"pending",表示这个Promise是待定的。
- 初始化onFulfilledCallback和onRejectedCallback回调数组,用于存储与此Promise对象相关的成功和失败回调函数。
- resolve和reject是executor的两个函数参数,它们改变Promise的状态并设置相应的值。
- 使用setTimeout将resolve和reject的执行放入异步队列中,以确保回调总是异步调用的。
- executor是在新的Promise对象创建时立即执行的函数,它的作用是开始异步操作。
resolve函数
- 检查当前Promise的状态是否为"pending",如果是,则将状态改变为"fulfilled",并保存解析的值。
- 遍历onFulfilledCallback数组,执行存储的所有成功回调。
reject函数
- 检查当前Promise的状态是否为"pending",如果是,则将状态改变为"rejected",并保存拒绝的理由。
- 遍历onRejectedCallback数组,执行存储的所有失败回调。
Promise.prototype.then函数
- then方法返回一个新的Promise(promise2)。
- 根据当前Promise(this)的状态执行相应的回调函数。
- 如果回调函数返回一个值,那么promise2应该被解析为这个值。
- 如果回调函数抛出一个错误,则promise2应该以这个错误被拒绝。
- 如果当前的Promise还处于"pending"状态,则将回调函数添加到相应的回调数组中等待执行。
promiseResolutionProcedure函数
- 这是一个用于处理返回值x的函数,以确定如何解析或拒绝promise2。
- 如果x等于promise2,会抛出TypeError异常,因为这会导致循环引用。
- 如果x是一个Promise,根据x的状态决定如何处理promise2。
- 如果x是一个对象或函数,尝试调用x.then并递归地调用promiseResolutionProcedure。
- 如果x是一个非Promise的值,或者没有then方法,用它的值解析promise2。
注意事项
- 确保所有的异常都能被捕获并导致Promise被拒绝。
- setTimeout用来确保回调函数异步执行,符合Promises/A+规范。