写这篇文章的初衷
- 了解Promise的内部执行机制
- 尝试封装一个mini版Promise
原生Promise使用
看出来了这里需要接收一个函数,像这样:
- Promise是一个构造函数,原型上绑定三个静态属性分别为then、catch、finally这几个静态方法
- 构造函数实例也有这几个钩子函数
开始封装
- 这里主要解释下代码执行机制
- 注释部分解释
// @ts-nocheck
class Promise2 {
//默认是pending状态
state = "pending"
//缓存因为异步执行函数
/**
* 像这样 new Promise((resolve,reject) => {
* setTimeout()
* resolve()
* })
*
*/
callbacks = []
private resolveOrReject(state, data, i) {
// 初始状态state是pending
if (this.state !== "pending") return
this.state = state
//nextTick 是我手写的异步调用栈,会在浏览器主线程执行完毕后触发
//你可以理解Promise.then触发后 最后会走到这里,并且它总会在最后执行
nextTick(() => {
this.callbacks.forEach(handle => {
if (typeof handle[i] === "function") {
let x
try {
x = handle[i].call(undefined, data)
} catch (e) {
return handle[2].reject(e)
}
handle[2].resolveWith(x)
}
})
})
}
/**
* 核心方法执行 resolveOrReject这个方法
*/
private resolve(result) {
this.resolveOrReject("fulfilled", result, 0)
}
private reject(reason) {
this.resolveOrReject("rejected", reason, 1)
}
constructor(fn) {
if (typeof fn !== "function") {
//构造函数默认必须接收一个函数、否则报错
throw new Error("The argument must be a function type!");
}
//执行传入的函数
/**
* new Promise((resolve, reject) => {})
* this.resolve.bind(this) ===> resolve
* this.reject.bind(this) ===> reject
*/
fn(this.resolve.bind(this), this.reject.bind(this))
}
// then接收两个非必填函数参数、并缓存到一个临时数组中
//最终为返回一个新的Promise实例
then(succeed?, fail?) {
const handle = []
if (typeof succeed === "function") {
handle[0] = succeed
}
if (typeof fail === "function") {
handle[1] = fail
}
// new Promise2(() => {}) 这里也是一个hack,会触发上面的构造器 ---> resolveOrReject(resolveOrReject会等到下面逻辑都执行完才会触发)
handle[2] = new Promise2(() => {})
//缓存到数组中方便下一个循环执行
this.callbacks.push(handle)
//这样做就可以链式调用
return handle[2]
}
private resolveWithSelf() {
this.reject(new TypeError())
}
private resolveWithPromise(x) {
x.then(
result => { this.resolve(result) },
reason => { this.reject(reason) }
)
}
private getThen(x) {
let then
try {
then = x.then
} catch (e) {
return this.reject(e)
}
return then
}
private resolveWithThenable(x) {
try {
x.then(
y => { this.resolveWith(y) },
r => { this.reject(r) }
)
} catch (e) {
this.reject(e)
}
}
/**
* 解决new Promise(() => {}).then(res => {
* return {
* e.g 1 返回普通对象
* e.g 2 返回Promise对象
* }
* 目的是链式调用
* })
*/
private resolveWithObject(x) {
let then = this.getThen(x)
if (then instanceof Function) {
this.resolveWithThenable(x)
} else {
this.resolve(x)
}
}
//对resolve() 或者 reject() 返回值进行二次处理
private resolveWith(x) {
if (this === x) {
this.resolveWithSelf()
} else if (x instanceof Promise2) {
this.resolveWithPromise(x)
} else if (x instanceof Object) {
this.resolveWithObject(x)
} else {
this.resolve(x)
}
}
}
export default Promise2
// 封装的异步调用方法
function nextTick(fn) {
if (process !== undefined && typeof process.nextTick === "function") {
return process.nextTick(fn)
} else {
var counter = 1
var observer = new MutationObserver(fn)
var textNode = document.createTextNode(String(counter))
observer.observe(textNode, {
characterData: true
})
counter = counter + 1
textNode.data = String(counter)
}
}
最后欢迎留言交流