难点与解决方案:
1. promise中包裹了异步任务的处理
- 实例调用then方法时,将then中的回调函数保存起来
- 当promise中的resolve或者reject执行时,执行then办法保存起来的回调函数
- 由于一个实例可以调用多次then方法,而每一个then的回调都要执行,因此存于一个数组中
2. then方法的回调返回值也是promise
- then返回的promise实例的状态和值,等同于then的回调返回的promis实例的状态和值
3. 异常穿透
- then方法中,判断第二个参数没有值(或者不是函数)
- 如果没有第二个参数,则重写该回调,使其为一个函数,并抛出上一个promise失败的结果,实现异常穿透
方式一:使用构造函数封装
function Promise(executor) {
this.PromiseState = 'pending'
this.PromiseResult = undefined
this.callbacks = []
function resolve(data) {
if (this.PromiseState !== 'pending') return
this.PromiseState = 'fulfilled'
this.PromiseResult = data
this.callbacks.forEach(item => {
if (item.onResolve) item.onResolve(data)
});
}
function reject(data) {
if (this.PromiseState !== 'pending') return
this.PromiseState = 'rejected'
this.PromiseResult = data
this.callbacks.forEach(item => {
if (item.onReject) item.onReject(data)
});
}
try {
executor(resolve.bind(this), reject.bind(this))
} catch (err) {
reject.call(this, err)
}
}
Promise.prototype.then = function (onResolve, onReject) {
let self = this
if (typeof onReject !== "function") onReject = err => { throw err }
if (typeof onResolve !== "function") onResolve = res => res
return new Promise((resolve, reject) => {
let callback = function (type) {
try {
let res = type(self.PromiseResult)
if (res instanceof Promise) {
res.then(r => {
resolve(r)
}, e => {
reject(e)
})
} else {
resolve(res)
}
} catch (err) {
reject(err)
}
}
if (this.PromiseState === 'fulfilled') {
callback(onResolve)
} else if (this.PromiseState === 'rejected') {
callback(onReject)
} else {
this.callbacks.push({
onResolve: function () {
callback(onResolve)
},
onReject: function () {
callback(onReject)
}
})
}
})
}
Promise.prototype.catch = function (onReject) {
return this.then(undefined, onReject)
}
方式二:class定义类
class Promise {
constructor(executor) {
this.PromiseState = 'pending'
this.PromiseResult = undefined
this.callbacks = []
try {
executor(this.resolve.bind(this), this.reject.bind(this))
} catch (error) {
this.reject.call(this, error)
}
}
resolve(data) {
if (this.PromiseState !== "pending") return
this.PromiseState = 'fulfilled'
this.PromiseResult = data
this.callbacks.forEach(item => {
item.onResolve(data)
})
}
reject(data) {
if (this.PromiseState !== "pending") return
this.PromiseState = 'rejected'
this.PromiseResult = data
this.callbacks.forEach(item => {
item.onReject(data)
})
}
then(onResolve, onReject) {
let self = this
if(typeof onResolve !== 'function') onResolve=res=>res
if(typeof onReject !== 'function') onReject=err=>{throw err}
return new Promise((resolve, reject) => {
function resultThen(type) {
try {
let res = type(self.PromiseResult)
if (res instanceof Promise) {
res.then(r => {
resolve(r)
}, e => {
reject(e)
})
} else {
resolve(res)
}
} catch (error) {
reject(error)
}
}
if (this.PromiseState === 'fulfilled') {
resultThen(onResolve)
} else if (this.PromiseState === 'rejected') {
resultThen(onReject)
} else {
this.callbacks.push({
onResolve: function () {
resultThen(onResolve)
},
onReject: function () {
resultThen(onReject)
}
})
}
})
}
catch(onReject){
return this.then(undefined,onReject)
}
}