根据尚硅谷promise讲解视频写的 链接
es5 function构造函数版,使用setTimeout模拟异步,但实际上promise应该是微任务
/* 疑难点
1.为什么要进行保存this
首先理清整个运行的逻辑,首先let p = new Promise(excutor)这个时候,
会自动执行Promise函数里面的内容,当走到this.PromiseState = 'pending',没有问题,this是实例对象p
但是当走到excutor(resolve,reject)的时候,会运行该函数
那么这个函数,又是外部指定的箭头函数,然后运行相对应的resolve()或者reject()
运行这个函数是window在调用,在函数内部的this就自然的变成了window,而不再是实例对象p
2.用queueMicrotask替换setTimeout,改成微任务
*/
// 声明构造函数
function Promise(excutor) {
// 添加属性,属于实例对象
this.PromiseState = 'pending'
this.PromiseResult = null
// 声明回调函数的属性,用数组,保存链式调用的多个回调
this.callbacks = []
// 保存实例对象的this值
const self = this
// 声明参数 resolve/reject
function resolve(data) {
// 此处的this为window
// console.log(this);
// 判断PromiseState是否改变过
if (self.PromiseState !== 'pending') return
// 1.修改对象状态(PromiseState),属于实例对象的
self.PromiseState = 'resolved'
// 2.设置对象结果值(PromiseResult)
self.PromiseResult = data
// 判断是否有保存好了的回调函数,forEach不会对空数组进行操作,所以省去了判断
//异步执行
setTimeout(() => {
self.callbacks.forEach(item => {
item.onResolved(data)
})
});
}
function reject(data) {
if (self.PromiseState !== 'pending') return
self.PromiseState = 'rejected'
self.PromiseResult = data
setTimeout(() => {
self.callbacks.forEach(item => {
item.onRejected(data)
})
});
}
//处理错误的时候,返回一个失败的promise对象
try {
// 同步调用 执行器函数
excutor(resolve, reject)
} catch (error) {
// 修改promise对象状态为失败
reject(error)
}
}
// 添加then 方法 , 实际上之所以说promise是异步的,指的是then方法里面执行onResolved是异步执行的
// promise创建的时候excutor等都是同步的,连then方法中也不全都是异步的,只有执行excutor中的参数resolve或者reject的时候才是异步
// 此处用setTimeout来模拟异步,但是官方的promise 是微任务,setTimeout是宏任务,网上好像是用的queueMicrotask()
Promise.prototype.then = function (onResolved, onRejected) {
const self = this
// 给onRejected指定一个函数,以防then只写一个参数,为了异常穿透
if (typeof onRejected !== 'function') {
onRejected = reason => {
throw reason
}
}
// 给onResolved指定一个函数,以防then不写参数,没传就返回的是undefined
if (typeof onResolved !== 'function') {
onResolved = value => value
}
return new Promise((resolve, reject) => {
// 封装反复使用的函数
function callback(type) {
try {
// 获取回调函数的执行结果
let result = type(self.PromiseResult)
if (result instanceof Promise) {
// 返回一个成功或者失败的Promise对象
result.then(v => {
//v是then回调内部return的结果
resolve(v)
}, r => {
reject(r)
})
} else {
// 返回一个成功的Promise对象
resolve(result)
}
} catch (error) {
reject(error)
}
}
// 调用回调函数 根据PromiseState
if (this.PromiseState === 'resolved') {
//then方法是由实例对象p调用的,所以可以根据this来得到PromiseState
// 模拟异步,但实际上应该用微任务,这里暂时不知道怎么加入微任务队列,好像是queueMicrotask()
setTimeout(() => {
callback(onResolved)
});
}
if (this.PromiseState === 'rejected') {
setTimeout(() => {
callback(onRejected)
});
}
// 判断pending状态,比如异步的时候,要在这里等待异步结果,要不然无法处理异步任务
// 另一个处理方式是,保存回调函数,让异步函数处理出结果的时候,判断有没有保存好的回调,如果有,那么就执行,如果没有那么说明异步,可以顺利通过then方法解决
if (this.PromiseState === 'pending') {
// 保存回调函数,用数组,保存链式调用的多个回调
this.callbacks.push({
onResolved: function () {
callback(onResolved)
},
onRejected: function () {