const PENDING = 'PENDING',
FULFILLED = 'FULFILLED',
REJECTED = 'REJECTED';
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
// 防止死循环
return reject(new TypeError('Chaining cycle detected for promise #<MyPromise>'))
}
let called = false;
if ((typeof x === 'object' && x !== null) || typeof x === 'function') {
try {
let then = x.then; // throw error
// 是一个对象或者函数 并且有then方法 认为是一个promise
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);
}
}
class MyPromise {
constructor(executor) {
// promise状态
this.status = PENDING;
// resolve的值
this.value = undefined;
// reject的原因
this.reason = undefined;
// 连续的resolve的回调函数
this.onResolveCallbacks = [];
// 连续的reject的回调函数
this.onRejectedCallbacks = [];
// 将resolve写成函数是因为promise中可以写异步任务(settimeout)
const resolve = (value) => {
if (this.status === PENDING) {
// 修改promise状态
this.status = FULFILLED;
this.value = value;
// 发布 (执行之前订阅的所有resolve函数)
this.onResolveCallbacks.forEach((fn) => fn());
}
}
const reject = (reason) => {
if (this.status === PENDING) {
this.status = REJECTED;
this.reason = reason;
// 发布
this.onRejectedCallbacks.forEach((fn) => fn());
}
}
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
// x 普通值 promise
then(onFulfilled, onRejected) {
// 如果是函数就执行 如果是空的则跳过当前then ( .then().then() )
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason };
// 因为then中不能存在this 如果要实现链式调用,则需要返回一个promise对象
let promise2 = new MyPromise((resolve, reject) => {
// 检查当前promise的状态
if (this.status === FULFILLED) {
// 因为promise2要是用了,但是还没有生成,为了生成promise2 将使用到的promise2部分的代码用settimeout包裹 执行部分放在event loop
setTimeout(() => {
try {
let x = onFulfilled(this.value);
// 为什么要写resolvePromise呢 因为onFulfilled的返回值类型不确定 可能还是一个promise或者是一个普通的数据类型 需要进一步判断
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
}
if (this.status === REJECTED) {
setTimeout(() => {
try {
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
}
//
// let promise = new Promise((resolve, reject)=>{
// ...
// })
// promise.then(()=>{setTimeout({resolve()})}
// promise.then(()=>{setTimeout({resolve()})})
//
// 因为setTimeout()异步执行,所以当执行then的时候 resolve还不能立即执行,所以需要发布订阅模式,先将需要执行的resolve回调函数放入队列中
if (this.status === PENDING) {
// 订阅
this.onResolveCallbacks.push(() => {
try {
let x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
this.onRejectedCallbacks.push(() => {
try {
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
}
});
return promise2;
}
catch (errorCallback) {
return this.then(null, errorCallback);
}
}
module.exports = MyPromise;