// promise的核心部分用到观察者模式(收集依赖 -> 触发通知 -> 取出依赖执行 的方式)
// 在下方有频繁提及
class MyPromise {
//先设置三种状态
static PENDING = "等待中";
static FULFILED = "接受";
static REJECTED = "拒绝";
//构造函数接收一个函数
constructor(fn) {
//为实例设置状态和结果
this.status = MyPromise.PENDING;
this.result = null;
//保存then中的函数 一个promise可能有多个then let p = new Promise() p.then p.then()
//promise是为了解决回调地域出现的,所以这也是promise的核心部分,利用回调实现异步的链式调用。
this.resolvedCallbacks = [];
this.rejectedCallbacks = [];
//因为this.resolve this.reject 是实例化后才调用的,属于默认调用,要绑定实例this,避免resolve方法中的this出错
fn(this.resolve.bind(this), this.reject.bind(this));
};
resolve(val) {
//promise.then要设置成异步 避免阻塞第三步和第四步代码
//使用settimeout将更改为异步 (当然也可以MutationObserver模拟微任务)
setTimeout(() => {
if (this.status !== MyPromise.PENDING) return; // 对应规范中的"状态只能由pending到fulfilled或rejected" 也就是说不能resolve了又reject
//判断状态是否是等待中,避免fullfiled又rejected
if (this.status === MyPromise.PENDING) {
this.status = MyPromise.FULFILED;
this.result = val;
//检是否有then放入的resolved函数
this.resolvedCallbacks.forEach((fn) => {
fn(this.result);
})
}
})
};
reject(val) {
//同理
setTimeout(() => {
if (this.status !== MyPromise.PENDING) return; // 对应规范中的"状态只能由pending到fulfilled或rejected" 也就是说不能resolve了又reject
//判断状态是否是等待中,避免fullfiled又rejected
if (this.status === MyPromise.PENDING) {
this.status = MyPromise.REJECTED;
this.result = val;
this.rejectedCallbacks.forEach((fn) => {
fn(this.result);
})
}
})
};
//then类方法接收两个参数
then(onFULFILLED, onREJECTED) {
//链式返回promise 由于是箭头函数 所以里面this不会出错
return new MyPromise((resolve, reject) => {
//这里是定义一个函数用于对promise和普通值返回 区分
const fulfilledFn = value => {
try {
//执行第一个(当前的)Promise的成功回调,并获取返回值
let x = onFULFILLED(value)
//分类讨论返回值,如果是Promise,那么等待Promise状态变更,否则直接resolve
//这里resolve之后,就能被下一个.then()的回调获取到返回值,从而实现链式调用
x instanceof MyPromise ? x.then(resolve, reject) : resolve(x)
} catch (error) {
reject(error)
}
}
//同理
const rejectedFn = error => {
try {
let x = onREJECTED(error)
x instanceof MyPromise ? x.then(resolve, reject) : resolve(x)
} catch (error) {
reject(error)
}
}
//这里的代码先于resolve函数,那么status是pendding
//所以要将这个函数保存起来,让resolve回调完后调用
//这里和resolvedCallbacks对应,是promise核心精华
if (this.status === MyPromise.PENDING) {
// //发布订阅
this.resolvedCallbacks.push(fulfilledFn);
this.rejectedCallbacks.push(rejectedFn);
}
//在then之前 promise状态已经改变 兼容以后promise.resolve().then()
if (this.status === MyPromise.FULFILED) {
fulfilledFn(this.result)
}
//同理
if (this.status === MyPromise.REJECTED) {
rejectedFn(this.reject)
}
})
}
}
//代码执行步骤自测 严格按照步骤执行顺序来
console.log("第一步");
var mp = new MyPromise((resolve) => {
console.log("第二步");
setTimeout(function () {
resolve("吃饭")
console.log("第四步")
}, 1500)
})
//then是异步方法,应该最后输出
mp.then(res => {
console.log("最后一步:", res)
//为新promise 提供值
// return res;
return new MyPromise((resolve) => {
resolve(res)
})
}).then(res => {
console.log(res)
})
console.log("第三步")
//代码自测
console.log("第一步");
var mp = new MyPromise((resolve) => {
console.log("第二步");
setTimeout(function () {
resolve("吃饭")
console.log("第四步")
}, 1500)
})
//then是异步方法,应该最后输出
mp.then(res => {
console.log("最后一步:", res)
//为新promise 提供值
// return res;
return new MyPromise((resolve) => {
resolve(res)
})
}).then(res => {
console.log(res)
})
console.log("第三步")