promise
const PENDING = 'PENDING'; // 等待
const FULFILLED = 'FULFILLED'; // 成功
const REJECTED = 'REJECTED'; // 失败
// 该方法核心就是判断x
const resolvePromise = (promise2, x, resolve, reject) => {
// 注意一个问题:promise2未定义;因为JS执行机制,new Promise没有执行完就传promise2 肯定是没有定义
// 此时我们需要异步来解决,先让new Promise执行完;然后在调resolvePromise方法将promise2传入,这样就可以获取的到了
// 判断x和promise2是不是同一个人,是则就报错
if(promise2 === x) {
return reject(new TypeError('Chaining cycle detected for promise #<Promise>'));
}
let called; // 内部测试的时候 会成功和失败都调用
//判断数据类型 typeof instanceof constructor toString
if(x !== null && (typeof x === 'object' || typeof x === 'function')) {
try {
let then = x.then; // 取then 有可能这个then属性是通过 defineProperty定义
if(typeof then === 'function') { // 当前有then方法,就姑且它是一个promise
then.call(x, y => { // y 可能还是一个promise,递归调用,直到解析为一个普通值为止
if (called) {
return
}
called = true;
resolvePromise(promise2, y, resolve, reject); // 采用成功的结果向下传递
}, r => {
if(called) {
return
}
called = true; // 防止多次调用成功和失败
reject(r); // 采用失败的结果向下传递
}); // 为什么不直接用x.then;是为了保证不用再次取then的值;因为取该值有可能取不到
} else {
// {then: 1}
resolve(x); // 说明x 是一个普通对象,直接成功即可
}
} catch (error) {
if(called) {
return
}
called = true;
reject(error);
}
} else {
// x 不是对象或函数 肯定是一个普通值
resolve(x); // 直接让promise2成功
}
}
class Promise {
constructor(executor) {
//不能相信用户的输入,一定要进行参数校验
if (typeof executor !== 'function') {
throw new TypeError(` Promise resolver ${executor} is not a function `);
}
this.status = PENDING;
this.value = undefined; // 成功的值
this.reason = undefined; // 失败的原因
this.onResolvedCallbacks = []; // 成功的回调的数组
this.onRejectedCallbacks = []; // 失败的回调的数组
// 成功函数
let resolve = (value) => {
// 屏蔽调用;防止调resolve后又调reject
if(this.status === PENDING) {
this.value = value;
this.status = FULFILLED;
this.onResolvedCallbacks.forEach(fn => fn()); // 发布
}
}
// 失败函数
let reject = (reason) => {
if(this.status === PENDING) {
this.reason = reason;
this.status = REJECTED;
this.onRejectedCallbacks.forEach(fn => fn());
}
}
try {
executor(resolve, reject); // 默认执行器会默认执行
} catch (error) {
reject(error); // 若执行时发生了错误。等价于调用了失败态
}
}
then(onfulfilled, onrejected) { // then 目前有两个参数
// onfulfilled, onrejected是可选参数
onfulfilled = typeof onfulfilled === 'function' ? onfulfilled : val => val;
onrejected = typeof onrejected === 'function' ? onrejected : err => {
throw err;
}
let promise2 = new Promise((resolve, reject) => {
// 同步情况
if(this.status === FULFILLED) {
setTimeout(() => {
try {
let x = onfulfilled(this.value);
// x可能是普通值 也可以是promise
// 判断x的值 ===》 promise2的状态 看是成功还是失败
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error); // 抛错的话直接调用promise2的reject方法
}
}, 0);
}
if(this.status === REJECTED) {
setTimeout(() => {
try {
let x = onrejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
}
// 异步情况
if(this.status === PENDING) {
// 如果是异步就先订阅好
this.onResolvedCallbacks.push(() => {
// todo...
setTimeout(() => {
try {
let x = onfulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
})
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onrejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
});
// 注意:加了异步setTimeout后;若代码里直接throw new Error抛错的话,上面的异常处理捕捉不到,因为是同步的,我们加了setTimeout后该部分就变成异步的了
// 所以我们需要在处理异步的情况时候也要加个异常处理try catch
}
});
return promise2;
}
}
// 延迟对象
Promise.defer = Promise.deferred = function () {
let dfd = {};
dfd.promise = new Promise((resolve, reject) => {
dfd.resolve = resolve;
dfd.reject = reject;
})
return dfd;
}
module.exports = Promise;
// 问题:1、为什么要加定时器?2、为什么在处理异步情况的时候也要加try-catch