const pending = ‘pending‘
resolved = ‘resolved‘
rejected = ‘rejected‘
//定义三种状态
class MyPromise {
//构造器 实例化的时候加载
constructor (cb) {
this._status = pending // 初始化状态
this._data = null // 成功传递的消息
this._error = null // 失败传递的消息
this.successSubs = [] // resolve后需要执行的回调队列
this.failSubs = [] // reject后需要执行的回调队列
resolve (_data) {
//执行resolve将状态改为 ‘resolved‘
if (this._status === pending) {
this._status = resolved
this._data = _data //传递的数据暂存
this.successSubs.forEach(fn => fn()) //发布之前订阅的方法
}
}
reject (_error) {
//执行reject将状态改为 ‘rejected‘
if (this._status === pending) {
this._status = rejected
this._error = _error //暂存错误信息
this.failSubs.forEach(fn => fn()) //发布之前订阅的方法
}
}
//实例化后constructor执行,执行cb的方法——即执行resolve和reject
if (typeof cb === ‘function‘) {
cb(this.resolve.bind(this), this.reject.bind(this)) // 绑定当前实例
} else if(cb && typeof cb !== ‘function‘) {
return new TypeError(‘MyPromise constructor must be a function‘)
}
}
// 封装一个方法来统一判断then里的参数执行完返回是不是一个新的promise
resolvePromise (x,resolve, reject) {
// 如果返回的是MyPromise实例
if (x instanceof MyPromise) {
x.then(data => {
resolve(data)
},
error => {
reject(error)
})
} else {
// 普通值:直接执行then返回的新promise方法的resolve,后一个then属于这个实例的,订阅队列也是属于这个实例的
resolve(x)
}
}
//class里写then方法,new实例后就可以 p.then,且为了可以继续链式调用,then里应返回一个新的promise
then (success, fail) {
// 链式调用 后一个then调用前一个then返回的promise实例
let p = new MyPromise((resolve, reject) => {
if (this._status === pending) {
//因为异步不能立即执行resove或者reject, promise实例还在pending状态调用了then方法,增加订阅者
if (success && typeof success === ‘function‘) {
this.successSubs.push(() => {
try {
// 用户调用then方法,callback函数,两种情况
// 1 非promise对象: return 什么就作为参数传递给下个then什么
// 2 promise对象:择要等用户的promise的有结果才执行下一个函数
let x = success(this._data)
// 统一封装到一个函数中处理
this.resolvePromise(x, resolve, reject)
} catch (e) {
reject(e)
}
})
}
if (fail && typeof fail === ‘function‘) {
this.failSubs.push(() => {
try {
let x = fail(this._error)
this.resolvePromise(x, resolve, reject)
} catch (e) {
reject(e)
}
})
}
} else if (this._status === resolved) {
try {
let x = success(this._data)
this.resolvePromise(x, resolve, reject)
} catch (e) {
reject(e)
}
} else if(this._status === rejected) {
try {
let x = fail(this._error)
this.resolvePromise(x, resolve, reject)
} catch (e) {
reject(e)
}
}
})
return p
}
}
...
// 直接调用了Promise.resolve方法
static resolve (value) {
return new MyPromise(resolve => {
resolve(value)
})
}
// 直接调用了Promise.reject
static reject(reason) {
return new MyPromise((undefined, reject) => {
reject(reason)
})
}
...