Promise简介
- 对于PromiseA+规范的详细描述: Promises/A+中文网
- 这里就不多赘述了,简单描述一下,首先我们知道
Promise主要是用来处理异步任务的- 它有三种状态(
pending, fulfilled, rejcted), 默认初始状态为pedning- 当
Promise状态改变时(未决->已决),后续then方法才会执行对应的逻辑then方法返回一个新的Promise(简称ProThen),Prothen的状态会与调用then的Promise相关联后续我们再详细展开Promise状态只能修改一次
简易版本Promise实现
- 基本的构造函数结构
- 简易的then方法实现
基本的构造函数结构
- promise传参必须是个函数(
excuter)- 函数是立刻调用的,函数有两个参数,且两个参数也是函数(
resolve,reject)- 调用
resolve时 promise 状态为fulfilled,调用reject时 promise状态为rejected,excuter执行报错时,promise状态也为rejected
代码实现
// 定义Promise 3种状态
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise {
// Promise状态
#PromiseState = PENDING
// Promise结果
#PromiseResult
// 修改Promise状态为拒绝
#reject = (resason) => {
this.#setPromiseState(REJECTED, resason)
}
// 修改Promise状态为成功
#resolve = (data) => {
this.#setPromiseState(FULFILLED, data)
}
// 设置Promise状态
#setPromiseState(state, data) {
if(this.#PromiseState !== PENDING) return
this.#PromiseState = state
this.#PromiseResult = data
}
// 构造函数执行
constructor(excuter) {
if(typeof excuter !== 'function') throw new TypeError('Promise resolver is not a function')
try {
excuter(this.#resolve, this.#reject)
} catch (error) {
console.error(error)
this.#reject(error)
}
}
}
测试代码
const p = new MyPromise((a, b) => {
throw new Error(111)
a('成功')
b('失败')
})
const p1 = new MyPromise((a, b) => {
a('成功')
throw new Error(111)
b('失败')
})
console.log(p)
console.log(p1)
小结
- 我们的代码做到到了改变
Promise状态和值只会改一次 exuter执行报错Promise会变为rejcted状态
简易的then方法实现
-
then函数必定返回一个新的
Promise(简称ProThen) -
then存在于构造函数的
Prototype上 -
支持链式调用(
new Promise().then().then()) -
对于同一个
Promise来说,可以无限支持promise.then,promise.then ...所以生成的Promise实例是不同的而对应的状态也并不会相同 -
前面说到ProThen的状态 会与调用then的Promise(简称Promise)状态相
关联, 这里我们大致展开梳理一下。- 5.1: then方法可传递两个参数(a, b), 且a, b都可为函数
- 5.2: a, b 为函数情况:
- 5.2.1:
Promise状态为resolve时调用 a,为rejected时调用 b - 5.2.2: 调用过程中代码执行无报错时:
- 5.2.2.1:调用 a且它的返回结果不为
PromiseLike,ProThen状态为resolve,结果为a的返回结果 - 5.2.2.2:调用b且它的返回结果不为
PromiseLike,ProThen状态为resolve,结果为b的返回结果 - 5.2.2.3:a或者b返回结果为
PromiseLike,则ProThen状态和结果与PromiseLike保持一致
- 5.2.2.1:调用 a且它的返回结果不为
- 5.5.3: 调用过程中代码执行报错时,
ProThen状态为rejected,结果为报错原因
- 5.2.1:
- 5.3:a, b 不为函数情况:
- 5.3.1:
ProThen状态与结果与Promise保持一致
- 5.3.1:
- 5.4:对于
PromiseLike解释:是一个对象或者函数,拥有then属性,且then是个函数
代码实现
class MyPromise {
// ...忽略
then(fulfilled, rejected) {
// 定义一个Promise
const promise = new MyPromise(() => {})
// 通过 实例属性拿到对应的方法
const resolve = promise.#resolve
const reject = promise.#reject
return promise
}
}
此时遇到了问题,上述代码中resolve 和 reject 是控制ProThen状态的函数,但是我们需要执行fulfilled 和 rejected 来知道ProThen的是什么状态,才能通过调用resolve 和 reject实现ProThen状态和结果的改变,应该怎么做?
- 可以使用对象映射的方式来存储对应的逻辑,设置表示当前处理函数的状态的属性(
currentState) 再通过属性描述符达到修改currentState后拿到对应的处理方式,方便后续使用
const obj = {
//成功状态的处理逻辑, excuteFn 对应 then(a, b)的 a, b 函数, setState 对应设置ProThen状态和结果
[FULFILLED]: {
excuteFn: fulfilled,
setState: resolve
},
// 拒绝状态的处理逻辑
[REJECTED]: {
excuteFn: rejected,
setState: reject
},
// 默认为pending
currentState: PENDING,
// 后续通过访问 obj.handler 可拿到不同处理逻辑
get handler() {
return this[this.currentState] || {}
}
}
- 我们再想一想,实现了对象映射存储对应逻辑,我们应该把这个对象放在哪里呢?以什么结构再存这个对象呢?
- 很简单,我们将对象放在调用then的Promise的实例中,并通过数组的方式存储
- why?为什么要通过数组的方式存储呢?我们可以想一下, 前面说到对于同一个
Promise,可以无限支持Promise.then, Promise.then ...,如果我们通过直接赋值的形式,那么永远只能拿到一个ProThen对应的操作逻辑,因此我们需要通过数组存储来达到目的。
具体代码实现
class MyPromise {
// ...忽略
// 存储PtoThen的相关逻辑
#queueTask = []
#createTask({ fulfilled, resolve, rejected, reject }) {
return {
//成功状态的处理逻辑, excuteFn 对应 then(a, b)的 a, b 函数, setState 对应设置ProThen状态和结果
[FULFILLED]: {
excuteFn: fulfilled,
setState: resolve
},
// 拒绝状态的处理逻辑
[REJECTED]: {
excuteFn: rejected,
setState: reject
},
// 默认为pending
currentState: PENDING,
// 后续通过访问 obj.handler 可拿到不同处理逻辑
get handler() {
return this[this.currentState] || {}
}
}
}
then(fulfilled, rejected) {
// 定义一个Promise
const promise = new MyPromise(() => {})
// 通过 实例属性拿到对应的方法
const resolve = promise.#resolve
const reject = promise.#reject
this.#queueTask.push(this.#createTask({
fulfilled,
resolve,
rejected,
reject
}))
return promise
}
}
ProThen状态设置的执行时机
- 调用then方法时,且
Promise状态改变的时候 - 当调用then方法的
Promise的状态改变的时候 ProThen的状态设置是放在微任务队列中触发的
注意
- 我们向数组中添加对应的
ProThen的处理逻辑时,是在调用then方法时
代码实现
class MyPromise {
// ...忽略
// 设置Promise状态
#setPromiseState(state, data) {
if(this.#PromiseState !== PENDING) return
this.#PromiseState = state
this.#PromiseResult = data
// +新增代码
this.#handleQueueTask()
}
then(fulfilled, rejected) {
// 定义一个Promise
const promise = new MyPromise(() => {})
// 通过 实例属性拿到对应的方法
const resolve = promise.#resolve
const reject = promise.#reject
this.#queueTask.push(this.#createTask({
fulfilled,
resolve,
rejected,
reject
}))
//+新增代码 执行queueTask队列
this.#handleQueueTask()
return promise
}
// 处理队任务
#handleQueueTask() {
// Promise状态为pending时, 不执行
if(this.#PromiseState === PENDING) return
// 循环ProThen任务队列, 并删除当前ProThen
for (let i = 0; i < this.#queueTask.length;) {
const task = this.#queueTask.shift()
// 改变ProThen状态执行逻辑 放入微队列
this.#runMicroTask(() => {
this.#handleSingleTask(task)
})
}
}
// 处理单个任务
#handleSingleTask(task) {
// 根据Promise的状态来执行ProThen的逻辑
const { excuteFn, setState } = this.#getHandler(task, this.#PromiseState)
// 设置 ProThen 为成功
const { setState: resolve } = this.#getHandler(task, FULFILLED)
// 设置 ProThen 为拒绝
const { setState: reject } = this.#getHandler(task, REJECTED)
// a, b 不是函数情况, ProThen 与 Promise 状态一致
if(typeof excuteFn !== 'function') {
setState(this.#PromiseResult)
return
}
// 执行 excuteFn函数
try {
const result = excuteFn(this.#PromiseResult)
// 结果是PromiseLike情况, 让ProThen与其状态一致
if(this.#isPromiseLike(result)) {
result.then(resolve, reject)
} else {
// 结果不是PromiseLike, ProThen状态为成功
resolve(result)
}
} catch (error) {
// 执行代码报错时ProThen 为拒绝
console.error(error)
reject(error)
}
}
// 判断是否为PromiseLike
#isPromiseLike(data){
return !!(data && (typeof data === 'object' || typeof data === 'function') && typeof data.then === 'function' )
}
// 设置并取出对应的ProThen执行逻辑
#getHandler(task, state) {
task.currentState = state
return task.handler
}
/**
* 把任务放进微队列中执行
* @param {Function} callback
* node环境中, 使用process.nextTick
* 浏览器环境, 优先使用queueMicroTask
* 最后, 使用 setTimeout
*/
#runMicroTask(callback) {
if(globalThis && globalThis.process && globalThis.process.nextTick) {
globalThis.process.nextTick(callback)
} else if(globalThis.queueMicrotask) {
globalThis.queueMicrotask(callback)
} else {
globalThis.setTimeout(callback, 0)
}
}
}
此时简易的Then方法实现就已完成。
完整代码
// 定义Promise 3种状态
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise {
// Promise状态
#PromiseState = PENDING
// Promise结果
#PromiseResult
// 修改Promise状态为拒绝
#reject = (resason) => {
this.#setPromiseState(REJECTED, resason)
}
// 修改Promise状态为成功
#resolve = (data) => {
this.#setPromiseState(FULFILLED, data)
}
/**
* 把任务放进微队列中执行
* @param {Function} callback
* node环境中, 使用process.nextTick
* 浏览器环境, 优先使用queueMicroTask
* 最后, 使用 setTimeout
*/
#runMicroTask(callback) {
if(globalThis && globalThis.process && globalThis.process.nextTick) {
globalThis.process.nextTick(callback)
} else if(globalThis.queueMicrotask) {
globalThis.queueMicrotask(callback)
} else {
globalThis.setTimeout(callback, 0)
}
}
// 设置Promise状态
#setPromiseState(state, data) {
if(this.#PromiseState !== PENDING) return
this.#PromiseState = state
this.#PromiseResult = data
this.#handleQueueTask()
}
constructor(excuter) {
if(typeof excuter !== 'function') throw new TypeError('Promise resolver is not a function')
try {
excuter(this.#resolve, this.#reject)
} catch (error) {
console.error(error)
this.#reject(error)
}
}
// 存储PtoThen的相关逻辑
#queueTask = []
#createTask({ fulfilled, resolve, rejected, reject }) {
return {
//成功状态的处理逻辑, excuteFn 对应 then(a, b)的 a, b 函数, setState 对应设置ProThen状态和结果
[FULFILLED]: {
excuteFn: fulfilled,
setState: resolve
},
// 拒绝状态的处理逻辑
[REJECTED]: {
excuteFn: rejected,
setState: reject
},
// 默认为pending
currentState: PENDING,
// 后续通过访问 obj.handler 可拿到不同处理逻辑
get handler() {
return this[this.currentState] || {}
}
}
}
// 判断是否为PromiseLike
#isPromiseLike(data){
return !!(data && (typeof data === 'object' || typeof data === 'function') && typeof data.then === 'function' )
}
// 设置并取出对应的ProThen执行逻辑
#getHandler(task, state) {
task.currentState = state
return task.handler
}
#handleSingleTask(task) {
// 根据Promise的状态来执行ProThen的逻辑
const { excuteFn, setState } = this.#getHandler(task, this.#PromiseState)
// 设置 ProThen 为成功
const { setState: resolve } = this.#getHandler(task, FULFILLED)
// 设置 ProThen 为拒绝
const { setState: reject } = this.#getHandler(task, REJECTED)
// a, b 不是函数情况, ProThen 与 Promise 状态一致
if(typeof excuteFn !== 'function') {
setState(this.#PromiseResult)
return
}
// 执行 excuteFn函数
try {
const result = excuteFn(this.#PromiseResult)
// 结果是PromiseLike情况, 让ProThen与其状态一致
if(this.#isPromiseLike(result)) {
result.then(resolve, reject)
} else {
// 结果不是PromiseLike, ProThen状态为成功
resolve(result)
}
} catch (error) {
// 执行代码报错时ProThen 为拒绝
console.error(error)
reject(error)
}
}
// 处理队任务
#handleQueueTask() {
// Promise状态为pending时, 不执行
if(this.#PromiseState === PENDING) return
// 循环ProThen任务队列, 并删除当前ProThen
for (let i = 0; i < this.#queueTask.length;) {
const task = this.#queueTask.shift()
// 改变ProThen状态执行逻辑 放入微队列
this.#runMicroTask(() => {
this.#handleSingleTask(task)
})
}
}
then(fulfilled, rejected) {
// 定义一个Promise
const promise = new MyPromise(() => {})
// 通过 实例属性拿到对应的方法
const resolve = promise.#resolve
const reject = promise.#reject
this.#queueTask.push(this.#createTask({
fulfilled,
resolve,
rejected,
reject
}))
// 执行queueTask队列
this.#handleQueueTask()
return promise
}
}
测试代码
const p1 = new MyPromise((a, b) => {
setTimeout(() => {
a(1)
b(9)
}, 1000)
})
const p2 = p1.then((data) => {
console.log(data)
return 2
}).then()
const p3 = p1.then(data => {
throw 111
}).then((data) => {
console.log('不会触发')
}, (reason) => {
console.log('触发', reason)
return 3
})
const p4 = p1.then(() => {
return new MyPromise((a, b) => {
b(4)
})
})
console.log(p1) // fuifilled 1
console.log(p2) // fuifilled 2
console.log(p3) // fulfilled 3
console.log(p4) // rejcted 4
小结
- 我们的then方法目前来说可以适用于大部分情况,对于一些特殊的场景还是有点缺陷,例如以下场景
// 对于嵌套多层 PromiseLike 情况
const p1 = new MyPromise(resolve => {
resolve(1)
}).then(() => {
return {
then(a, b) {
a({
then(a1, b1){
a1(2)
}
})
}
}
})
console.log(p1)
// 对于resolve(Promise) 的情况
const p2 = new MyPromise(resolve => {
resolve(new MyPromise(res => res(1)))
})
console.log(p2)
// 对于循环引用只身的情况
const p3 = new MyPromise(resolve => {
resolve()
}).then(() => {
return p3
})
console.log(p3)
- 对于PromiseA+规范,这些问题肯定都是要解决的,因此下面我们开始解决这些问题,实现满足
PromiseA+的then
PromiseA+的 then 的实现
- 对于它的解释,推荐查看开头的PromiseA+链接,Promises/A+中文网
修改地方
- 对于PromiseA+的规范查看后,发现代码主要问题有以下几点需要修改和实现
- 对于then调用返回结果是
PromiseLike的处理,我们写的有点简洁了,官方明确了好几点要求,对于PromiseLike.then的调用: 1. this指向,2. then(a, b)中,a 和 b 以及 then()出错了,我们应该只执行最先执行的,忽略其他的 - 对于是否循环引用了
Promise我们压根没做判断 - 对于
resolve(Promise)我们也需要修改优化
修改后的代码
class MyPromise {
// ... 忽略
constructor(excuter) {
if(typeof excuter !== 'function') throw new TypeError('Promise resolver is not a function')
let isInvoke = false
try {
// 修改 excuter
excuter((y) => {
if(isInvoke) return
isInvoke = true
this.#resolverPromise(this, y, {
resolve: this.#resolve,
reject: this.#reject
})
}, this.#reject)
} catch (error) {
console.error(error)
this.#reject(error)
}
}
// + 新增代码
/**
*
* @param {Promise} promise ProThen
* @param {any} x resolve(a)传参, 或者 then(a, b), a, b调用的结果
* @param {Object} param2
* @param { Function } resolve 设置 ProThen 成功
* @param { Function } reject 设置 ProThen 拒绝
* @param { Array } serialPromiseList 串行的 x 集合 (可相关代码删除, 不影响测试结果)
*/
#resolverPromise(promise, x, { resolve, reject, serialPromiseList = [] }) {
try {
// 判断 Promise 与 x 是否为同一值(本质也是循环引用)
if(promise === x) throw new TypeError('promise and x cannot refer to the same object')
// 判断是否循环引用了Promise
if(serialPromiseList.includes(x)) throw new TypeError('Chaining cycle detected for promise')
// 先排除 x 不为对象和函数, 或者为null的情况
if(typeof x !== 'object' && typeof x !== 'function' || x === null) {
resolve(x)
return
}
// 走到这说明 x 是对象 或者 函数的情况判断
// 声明一个变量then 尝试将 x.then 赋值给then
const then = x.then
// 判断then是否为函数
if(typeof then !== 'function') {
resolve(x)
return
}
// 走到这说明 then 是个函数
// 1. 调用then并将this指向x, 并传递两个函数 (resolvePromise, rejectPromise)
// 2. 执行then调用时出现错误, 或 resolvePromise, rejectPromise 同时被调用时,确保只会调用一次,忽略剩下的调用, (这里不进行判断逻辑也没问题, 因为在 reject 或 resolve 中也进行了判断, 保证了Promise 改变状态只会触发一次, 但是测试Promise会不通过)
// 3. 如果 resolvePromise 以值 y 为参数被调用,则继续运行 [[Resolve]](promise, y)
let isInvoke = false
try {
then.call(x, (y) => {
if(isInvoke) return
isInvoke = true
this.#resolverPromise(promise, y, {
resolve,
reject,
serialPromiseList: [...serialPromiseList, x]
})
}, (reason) => {
if(isInvoke) return
isInvoke = false
reject(reason)
})
} catch (error) {
if(isInvoke) return
isInvoke = true
console.error(error)
reject(error)
}
} catch (error) {
console.error(error)
reject(error)
}
}
// 创建任务
#createTask({ promise, fulfilled, resolve, rejected, reject }) {
return {
[FULFILLED]: {
// 修改代码
excuteFn: typeof fulfilled === 'function' ? fulfilled : (data) => data,
setState: resolve
},
[REJECTED]: {
// 修改代码
excuteFn: typeof rejected === 'function' ? rejected : (reason) => { throw reason },
setState: reject
},
currentState: PENDING,
// + 新增代码 ProThen
promise,
get handler() {
return this[this.currentState] || {}
}
}
}
// 处理单个任务
#handleSingleTask(task) {
// 根据Promise的状态来执行ProThen的逻辑
const { excuteFn } = this.#getHandler(task, this.#PromiseState)
// 设置 ProThen 为成功
const { setState: resolve } = this.#getHandler(task, FULFILLED)
// 设置 ProThen 为拒绝
const { setState: reject } = this.#getHandler(task, REJECTED)
// 执行 excuteFn函数
try {
// 执行excuteFn 拿到 结果
const result = excuteFn(this.#PromiseResult)
// 进行相关判断,对ProThen 进行 不同操作
this.#resolverPromise(task.promise, result, {
resolve,
reject
})
} catch (error) {
// 执行代码报错时ProThen 为拒绝
console.error(error)
reject(error)
}
}
}
完整代码
// 定义Promise 3种状态
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise {
// Promise状态
#PromiseState = PENDING
// Promise结果
#PromiseResult
// 修改Promise状态为拒绝
#reject = (resason) => {
this.#setPromiseState(REJECTED, resason)
}
// 修改Promise状态为成功
#resolve = (data) => {
this.#setPromiseState(FULFILLED, data)
}
/**
* 把任务放进微队列中执行
* @param {Function} callback
* node环境中, 使用process.nextTick
* 浏览器环境, 优先使用queueMicroTask
* 最后, 使用 setTimeout
*/
#runMicroTask(callback) {
if(globalThis && globalThis.process && globalThis.process.nextTick) {
globalThis.process.nextTick(callback)
} else if(globalThis.queueMicrotask) {
globalThis.queueMicrotask(callback)
} else {
globalThis.setTimeout(callback, 0)
}
}
// 设置Promise状态
#setPromiseState(state, data) {
if(this.#PromiseState !== PENDING) return
this.#PromiseState = state
this.#PromiseResult = data
this.#handleQueueTask()
}
constructor(excuter) {
if(typeof excuter !== 'function') throw new TypeError('Promise resolver is not a function')
let isInvoke = false
try {
excuter((y) => {
if(isInvoke) return
isInvoke = true
this.#resolverPromise(this, y, {
resolve: this.#resolve,
reject: this.#reject
})
}, this.#reject)
} catch (error) {
console.error(error)
this.#reject(error)
}
}
// 存储PtoThen的相关逻辑
#queueTask = []
#createTask({ promise, fulfilled, resolve, rejected, reject }) {
return {
//成功状态的处理逻辑, excuteFn 对应 then(a, b)的 a, b 函数, setState 对应设置ProThen状态和结果
[FULFILLED]: {
excuteFn: typeof fulfilled === 'function' ? fulfilled : (data) => data,
setState: resolve
},
// 拒绝状态的处理逻辑
[REJECTED]: {
excuteFn: typeof rejected === 'function' ? rejected : (reason) => { throw reason },
setState: reject
},
// 默认为pending
currentState: PENDING,
// promise
promise,
// 后续通过访问 obj.handler 可拿到不同处理逻辑
get handler() {
return this[this.currentState] || {}
}
}
}
// 设置并取出对应的ProThen执行逻辑
#getHandler(task, state) {
task.currentState = state
return task.handler
}
/**
*
* @param {Promise} promise ProThen
* @param {any} x resolve(a)传参, 或者 then(a, b), a, b调用的结果
* @param {Object} param2
* @param { Function } resolve 设置 ProThen 成功
* @param { Function } reject 设置 ProThen 拒绝
* @param { Array } serialPromiseList 串行的 x 集合 (可相关代码删除, 不影响测试结果)
*
*/
#resolverPromise(promise, x, { resolve, reject, serialPromiseList = [] }) {
try {
// 判断 Promise 与 x 是否为同一值(本质也是循环引用)
if(promise === x) throw new TypeError('promise and x cannot refer to the same object')
// 判断是否循环引用了Promise
if(serialPromiseList.includes(x)) throw new TypeError('Chaining cycle detected for promise')
// 先排除 x 不为对象和函数, 或者为null的情况
if(typeof x !== 'object' && typeof x !== 'function' || x === null) {
resolve(x)
return
}
// 走到这说明 x 是对象 或者 函数的情况判断
// 声明一个变量then 尝试将 x.then 赋值给then
const then = x.then
// 判断then是否为函数
if(typeof then !== 'function') {
resolve(x)
return
}
// 走到这说明 then 是个函数
// 1. 调用then并将this指向x, 并传递两个函数 (resolvePromise, rejectPromise)
// 2. 执行then调用时出现错误, 或 resolvePromise, rejectPromise 同时被调用时,确保只会调用一次,忽略剩下的调用, (这里不进行判断逻辑也没问题, 因为在 reject 或 resolve 中也进行了判断, 保证了Promise 改变状态只会触发一次, 但是测试Promise会不通过)
// 3. 如果 resolvePromise 以值 y 为参数被调用,则继续运行 [[Resolve]](promise, y)
let isInvoke = false
try {
then.call(x, (y) => {
if(isInvoke) return
isInvoke = true
this.#resolverPromise(promise, y, {
resolve,
reject,
serialPromiseList: [...serialPromiseList, x]
})
}, (reason) => {
if(isInvoke) return
isInvoke = false
reject(reason)
})
} catch (error) {
if(isInvoke) return
isInvoke = true
console.error(error)
reject(error)
}
} catch (error) {
console.error(error)
reject(error)
}
}
#handleSingleTask(task) {
// 根据Promise的状态来执行ProThen的逻辑
const { excuteFn } = this.#getHandler(task, this.#PromiseState)
// 设置 ProThen 为成功
const { setState: resolve } = this.#getHandler(task, FULFILLED)
// 设置 ProThen 为拒绝
const { setState: reject } = this.#getHandler(task, REJECTED)
// 执行 excuteFn函数
try {
const result = excuteFn(this.#PromiseResult)
this.#resolverPromise(task.promise, result, {
resolve,
reject
})
} catch (error) {
// 执行代码报错时ProThen 为拒绝
console.error(error)
reject(error)
}
}
// 处理队任务
#handleQueueTask() {
// Promise状态为pending时, 不执行
if(this.#PromiseState === PENDING) return
// 循环ProThen任务队列, 并删除当前ProThen
for (let i = 0; i < this.#queueTask.length;) {
const task = this.#queueTask.shift()
this.#runMicroTask(() => {
this.#handleSingleTask(task)
})
}
}
then(fulfilled, rejected) {
// 定义一个Promise
const promise = new MyPromise(() => {})
// 通过 实例属性拿到对应的方法
const resolve = promise.#resolve
const reject = promise.#reject
this.#queueTask.push(this.#createTask({
promise,
fulfilled,
resolve,
rejected,
reject
}))
// 执行queueTask队列
this.#handleQueueTask()
return promise
}
}
MyPromise.deferred = function () {
var result = {};
result.promise = new MyPromise(function (resolve, reject) {
result.resolve = resolve;
result.reject = reject;
});
return result;
}
module.exports = MyPromise
测试工具测试Promise
- 下载
promises-aplus-tests测试包
npm i promises-aplus-tests
- package.json 中添加脚本
"scripts": {
"test": "promises-aplus-tests 你的js文件"
// 例如我的文件叫 indexTest.js
"test": "promises-aplus-tests indexTest.js"
},
- MyPromise代码文件中加入以下
MyPromise.deferred = function () {
var result = {};
result.promise = new MyPromise(function (resolve, reject) {
result.resolve = resolve;
result.reject = reject;
});
return result;
}
module.exports = MyPromise
- 运行脚本的js文件中
const promisesAplusTests = require('promises-aplus-tests');
const adapter = require('../index1'); // MyPromise文件路径
promisesAplusTests(adapter, function (err) {
if (err) {
console.error('Promises/A+ 测试失败:');
console.error(err);
} else {
console.log('Promises/A+ 测试通过');
}
});
- 运行命令
npm run test - 测试通过情况
至此,PromiseA+ 规范我们全部完成,如有疑问或者错误描述的地方,可评论或者私信,我会及时修改和回复,谢谢