满足Promise A+规范的Promise
Promise的A+规范的重点就是then方法, 只要是一个对象有then方法, 就满足PromiseA+规范
ES6的Promise
比PromiseA+规范, 多了一些方法, 比如catch, resolve, finally, reject...
注意点:
- 当Promise内部, 抛出一个错误的时候, 会直接去调用reject方法, 如果这个错误是异步抛出的, Promise不能捕捉到这个错误, 状态依然会是pending
- Promise.then这个方法, 是Promise对象的灵魂, then这个方法需要放在微任务队列中, 所以就有了不同环境下的处理办法, 在node环境下, 会使用nextTick去, 如果是浏览器环境, 就去使用MutationObserver, 如果都不行, 就会使用setTimeout方法
// 定义状态
const pending = "pending"
const fulfilled = "fulfilled"
const rejected = "rejected"
class MyPromise {
#state = pending
#result = undefined
#handlers = []
constructor(execute) {
const resolve = (data) => {
this.#changeState(fulfilled, data)
}
const reject = (err) => {
this.#changeState(rejected, err)
}
// 如果执行期间报错, 我就帮你去改变状态
// 注意: 这个不能捕获异步的错误
try {
execute(resolve, reject)
} catch (error) {
reject(error)
}
}
#changeState(state, res) {
if (this.#state !== pending) return
this.#state = state
this.#result = res
// console.log(this.#state, this.#result);
this.#run()
}
#isPromiseLike(value) {
if(value != null && (typeof value === 'function' || typeof value === 'object')) {
return typeof value.then === 'function'
} else {
return false
}
}
// 微任务队列中, then的回调是需要 放到微任务队列中去
#runMicroTask(fn) {
// 如果是node环境
if(typeof process === 'object' && typeof process.nextTick === 'function') {
process.nextTick(fn)
}
// 如果是浏览器环境
else if(typeof MutationObserver === 'function') {
const ob = new MutationObserver(fn)
const textNode = document.createTextNode('1')
ob.observe(textNode, {
characterData: true
})
textNode.data = '2'
}
else {
setTimeout(fn, 0)
}
}
#runOne(callback, resolve, reject) {
this.#runMicroTask(() => {
if(typeof callback !== 'function') {
// 去值穿透
const settled = this.#state === fulfilled ? resolve : reject
settled(this.#result)
return
}
try {
const data = callback(this.#result)
if(this.#isPromiseLike(data)) {
data.then(resolve, reject)
} else {
resolve(data)
}
} catch (error) {
reject(error)
}
})
}
#run() {
// then解决的第一个问题, 什么时候去运行回调
if(this.#state === pending) return
// 挨个从数组中拿到, 进行处理
while(this.#handlers.length) {
const { onFullfilled, onRejected, resolve, reject } = this.#handlers.shift()
if (this.#state === fulfilled) {
this.#runOne(onFullfilled, resolve, reject)
} else if (this.#state === rejected) {
this.#runOne(onRejected, resolve, reject)
}
}
}
// onFullfilled: 成功的时候, 的回调
// onRejected: 失败的时候, 的回调
// then只需要, 解决两件事,
// 1.啥时候运行传入的回调,
// 2.返回promise, 这个promise什么时候完成, 什么时候失败
// ---- 1.then返回的promise, then的参数, 不是一个回调函数, 是一个普通的值
// 值穿透: then之前的promise是成功, then返回的promise就是成功, 反之同理
// ---- 2.then的参数, 是回调函数, 利用trycatch去执行, 成功就resolve结果, 失败就reject
// ---- 3. 回调函数的返回结果, 是一个promise, 去判断是否是promise
then(onFullfilled, onRejected) {
return new Promise((resolve, reject) => {
// 在handler中记录, 这四个函数
this.#handlers.push({
onFullfilled,
onRejected,
resolve,
reject
});
this.#run();
})
}
// ES6的promise出现的方法
catch(onRejected) {
return this.then(undefined, onRejected)
}
// 无论成功还是失败都执行
finally(onFinally) {
return this.then(data => {
onFinally()
return data
}, err => {
onFinally()
throw err
})
}
static resolve(value) {
// 如果值是一个promise, 直接返回他
/*
官方解释
如果该值本身就是一个 Promise,那么该 Promise 将被返回;
如果该值是一个 thenable 对象,Promise.resolve() 将调用其 then() 方法及其两个回调函数;
否则,返回的 Promise 将会以该值兑现。
*/
if(value instanceof MyPromise) return value
let _resolve,_reject;
const p = new MyPromise((resolve, reject) => {
_resolve = resolve
_reject = reject
})
// 如果满足promiseA+规范, 有then方法
if(p.#isPromiseLike(value)) {
value.then(_resolve, _reject)
}
// 如果是一个普通的值, 普通的对象
else {
_resolve(value)
}
return p
}
// 静态方法返回一个已拒绝(rejected)的 Promise 对象,拒绝原因为给定的参数。
static reject(error) {
return new MyPromise((resolve, reject) => {
reject(error)
})
}
}