function MyPromise(callback) {
// 状态
this.status = "pending";
this.value = undefined; // 成功时的值
this.reason = undefined; // 失败时的值
this.onFulfilledCallbacks = []; // 用于保存成功时的回调函数数组
this.onRejectedCallbacks = []; // 用于保存失败时的回调函数数组
// 处理成功的信息
const resolve = (data) => {
if (this.status === "pending") {
this.status = 'fulfilled';
this.value = data;
this.onFulfilledCallbacks.forEach(fn => fn()); // 执行成功时的回调函数
}
};
// 处理失败的信息
const reject = (data) => {
if (this.status === "pending") {
this.status = 'rejected';
this.reason = data;
this.onRejectedCallbacks.forEach(fn => fn()); // 执行失败时的回调函数
}
};
// 用try-catch处理callback中的错误
try {
callback(resolve, reject);
} catch (e) {
reject(e);
}
}
// 重写then方法
MyPromise.prototype.then = function (onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v => v;
onRejected = typeof onRejected === 'function' ? onRejected : e => { throw e; };
return new MyPromise((resolve, reject) => {
if (this.status === 'fulfilled') {
setTimeout(() => {
try {
let x = onFulfilled(this.value);
resolvePromise(x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
} else if (this.status === 'rejected') {
setTimeout(() => {
try {
let x = onRejected(this.reason);
resolvePromise(x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
} else {
// pending 状态
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
try {
let x = onFulfilled(this.value);
resolvePromise(x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onRejected(this.reason);
resolvePromise(x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
}
});
};
// resolvePromise方法用于处理then返回的Promise
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(new TypeError('Chaining cycle detected for promise'));
}
let called;
if (x instanceof MyPromise) {
if (x.status === 'pending') {
x.then(y => resolvePromise(promise2, y, resolve, reject),
e => reject(e));
} else {
x.then(resolve, reject);
}
} else if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
try {
let then = x.then;
if (typeof then === 'function') {
then.call(x, y => {
if (called) return;
called = true;
resolvePromise(promise2, y, resolve, reject);
}, r => {
if (called) return;
called = true;
reject(r);
});
} else {
resolve(x);
}
} catch (e) {
if (called) return;
called = true;
reject(e);
}
} else {
resolve(x);
}
}