// _Promise.js
// 先定义三个常量表示状态
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
function isFunction(fn) {
return typeof fn === 'function';
}
function isObject(ob) {
return typeof ob === 'object';
}
function isNull(value) {
return value === null;
}
function resolvePromise(promise, value, resolve, reject) {
// 自己调用自己
if (promise === value) {
return reject(new TypeError('Chaining cycle detected for promise #<Promise>'));
}
// if (value instanceof _Promise) {
// value.then(resolve, reject);
// } else {
// resolve(value);
// }
if (isFunction(value) || isObject(value)) {
if (isNull(value)) {
return resolve(value);
}
let then;
try {
then = value.then;
} catch (err) {
return reject(err);
}
if (isFunction(then)) {
// then里面resolve 和 reject 只能有一个执行,因此加一个锁。
let called = false;
try {
then.call(
// this 指向value
value,
// resolve
val => {
if (called) return;
called = true;
resolvePromise(promise, val, resolve, reject);
},
// reject
val => {
if (called) return;
called = true;
reject(val);
}
);
} catch (err) {
if (called) return;
return reject(err);
}
} else {
// 如果直接是一个值,就resolve它
return resolve(value);
}
} else {
// 如果直接是一个值,就resolve它
return resolve(value);
}
}
// 新建 _Promise 类
class _Promise {
constructor(executor) {
// executor 是一个执行器,进入会立即执行
// 并传入resolve和reject方法
try {
executor(this.resolve, this.reject);
} catch (error) {
this.reject(error);
}
}
// 储存状态的变量,初始值是 pending
status = PENDING;
// 成功之后的值
value = null;
// 失败之后的原因
reason = null;
// 存储成功回调函数
onFulfilledCallbackList = [];
// 存储失败回调函数
onRejectedCallbackList = [];
// 更改成功后的状态
resolve = value => {
// 只有状态是等待,才执行状态修改
if (this.status === PENDING) {
// 状态修改为成功
this.status = FULFILLED;
// 保存成功之后的值
this.value = value;
// resolve里面将所有成功的回调拿出来执行
while (this.onFulfilledCallbackList.length) {
// Array.shift() 取出数组第一个元素,然后()调用,shift不是纯函数,取出后,数组将失去该元素,直到数组为空
this.onFulfilledCallbackList.shift()(value);
}
}
};
// 更改失败后的状态
reject = reason => {
// 只有状态是等待,才执行状态修改
if (this.status === PENDING) {
// 状态成功为失败
this.status = REJECTED;
// 保存失败后的原因
this.reason = reason;
// resolve里面将所有失败的回调拿出来执行
while (this.onRejectedCallbackList.length) {
this.onRejectedCallbackList.shift()(reason);
}
}
};
then(onFulfilled, onRejected) {
const realOnFulfilled = isFunction(onFulfilled) ? onFulfilled : value => value;
const realOnRejected = isFunction(onRejected)
? onRejected
: reason => {
throw reason;
};
// 为了链式调用这里直接创建一个 _Promise,并在后面 return 出去
const subPromise = new _Promise((resolve, reject) => {
const fulfilledMicrotask = () => {
// 创建一个微任务等待 subPromise 完成初始化
// 开始采用的queueMicrotask来模拟微任务,但是queueMicrotask是使用promise搞得,这里就有点套娃的柑橘了,所以换成了setTimeout
// queueMicrotask(() => {
// });
setTimeout(() => {
try {
// 获取成功回调函数的执行结果
const x = realOnFulfilled(this.value);
// 传入 resolvePromise 集中处理
resolvePromise(subPromise, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
};
const rejectedMicrotask = () => {
// 创建一个微任务等待 subPromise 完成初始化
setTimeout(() => {
try {
// 调用失败回调,并且把原因返回
const x = realOnRejected(this.reason);
// 传入 resolvePromise 集中处理
resolvePromise(subPromise, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
// queueMicrotask(() => {
// });
};
const statusHandleMap = {
[FULFILLED]: fulfilledMicrotask,
[REJECTED]: rejectedMicrotask,
[PENDING]: () => {
this.onFulfilledCallbackList.push(fulfilledMicrotask);
this.onRejectedCallbackList.push(rejectedMicrotask);
}
};
statusHandleMap[this.status]();
// 判断状态
// if (this.status === FULFILLED) {
// fulfilledMicrotask();
// } else if (this.status === REJECTED) {
// rejectedMicrotask();
// } else if (this.status === PENDING) {
// // 等待
// // 因为不知道后面状态的变化情况,所以将成功回调和失败回调存储起来
// // 等到执行成功失败函数的时候再传递
// this.onFulfilledCallbacks.push(fulfilledMicrotask);
// this.onRejectedCallbacks.push(rejectedMicrotask);
// }
});
return subPromise;
}
// resolve 静态方法
static resolve(parameter) {
console.log('value parameter');
// 如果传入 _Promise 就直接返回
if (parameter instanceof _Promise) {
return parameter;
}
// 转成常规方式
return new _Promise(resolve => {
resolve(parameter);
});
}
// reject 静态方法
static reject(reason) {
return new _Promise((resolve, reject) => {
reject(reason);
});
}
}
// export { _Promise };
// module.exports = _Promise;