promise A+ 规范
必须是对象,且必须含有then方法
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
// 模拟微队列
function runMicroTask(callback) {
if(process && process.nextTick) {
process.nextTick(callback)
} else if(MutationObserver) {
const observer = new MutationObserver(callback)
const p = document.createElement('p')
observer.observe(p, {
childList: true // 监听p的子元素,元素发生变化后运行回调
}
p.innerHTML = 1
} else {
setTimeout(callback, 0)
}
}
//判断是否符合promise A+规范
function isPromise(obj) {
return !!(obj && typeof obj === 'object' && typeof obj.then === 'function')
}
class MyPromise {
constructor(handler) {
if(typeof handler !== 'function') {
throw TypeError('handler must be a function!')
}
this._status = PENDING
this._value = undefined
this._handlers = [] // 事件数组
try {
handler(this._resolve.bind(this), this._reject.bind(this))
} catch(err) {
this._reject(err)
}
}
//将事件推入队列等待执行
_pushHandler(executor, status, resolve, reject) {
this._handlers.push({executor, status, resolve, reject})
}
// 将事件从队列中取出依次执行
_runHandlers() {
if(this._status === PENDING) return
while(this._handlers[0]) {
_runHandler(this._handlers[0])
this._handlers.shift()
}
}
// 执行某个事件
_runHandler({ executor, status, resolve, reject }) { // 将参数解构以防this指向问题
runMicroTask(() => {
if(this._status !== status) return
if(typeof executor !== 'function') {
this._status === FULFILLED ? resolve(this._value) : reject(this._value)
}
try {
const result = executor(this._value)
if(isPromise(result)) {
result.then(resolve, reject)
} else {
resolve(result)
}
} catch(err) {
reject(err)
}
})
}
_resolve(data) {
if(this._status !== PENDING) {
return
}
this._value = data
this._status = FULFILLED
this._runHandlers() // 状态改变依次运行队列的函数
}
_reject(err) {
if(this._status !== PENDING) {
return
}
this._value = err
this._status = REJECTED
this._runHandlers() // 状态改变依次运行队列的函数
}
then(onFulfilled, onRejected) {
return new MyPromise((resolve, reject) => {
this._pushHandlers(onFulfilled, FULFULLED, resolve, reject)
this._pushHandlers(onRejected, REJECTED, resolve, reject)
this._runHandlers() // 状态改变依次运行队列的函数
})
}
catch(onRejected) {
return this.then(null, onRejected)
}
finally(onSettled) {
return this.then((data) => {
onSettled()
return data
}, (err) => {
onSettled()
throw err
}}
}
// 静态方法
static resolve(data) {
if(data instaceof MyPromise) {
return data
}
return new MyPromise((resolve, reject) => {
if(isPromise(data)) {
data.then(resolve, reject)
} else {
resolve(data)
}
})
}
static reject(err) {
return new MyPromsie((resolve, reject) => {
reject(err)
})
}
static all(proms) {
return new MyPromsie((resolve, reject) => {
try {
let results = []
let count = 0
let fulfilledCount = 0
for(let p of proms) {
let i = count;
count++
MyPromse.resolve(p).then(data => {
fulfilledCount++
results[i] = data
if(count === fulfilledCount) {
resolve(results)
}
}, reject)
}
if(count === 0) { // 当数组长度为0时
resolve(results)
}
} catch(err) {
reject(err)
}
})
}
static allSettled(proms) {
const arr = []
for(const p of proms) {
arr.push(MyPromsie.resolve(p).then(data => ({ value: data, status: FULFILLED}), err => ({ reason: err, status: REJECTED })))
}
return MyPromise.all(arr)
}
static race(proms) {
return new MyPromise((resolve, reject) => {
for(const p of proms) {
MyPromise.resolve(p).then(resolve, reject)
}
})
}
}