1.1 构造函数
创建MyPromise并设置构造函数;
class MyPromise{
constructor(func) {
// 定义resolve/reject
const resolve = (result) => {
console.log('resolve执行',result)
}
const reject = (result) => {
console.log('reject执行',result)
}
// 执行回调函数
func(resolve,reject)
}
}
1.2 状态与原因
为MyPromise添加状态(pending:待定、fulfilled:已兑现、rejected:已拒绝)与原因;
// 状态
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise{
// 添加状态/原因
state = PENDING
result = undefined
constructor(func) {
// 修改状态pending -> fulfilled/rejected
const resolve = (result) => {
if(this.state === PENDING) {
this.state = FULFILLED
this.result = result
}
}
const reject = (result) => {
if(this.state === PENDING) {
this.state = REJECTED
this.result = result
}
}
// 执行回调函数
func(resolve,reject)
}
}
1.3 .then方法
1.3.1 成功和失败的回调
......
class MyPromise{
......
then(onFulfilled,onRejected) {
// 判断
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : x => x
onRejected = typeof onRejected === 'function' ? onRejected : x => { throw x }
// 执行回调
if(this.state === FULFILLED) {
onFulfilled(this.result)
} else if (this.state === REJECTED) {
onRejected(this.result)
}
}
}
1.3.2 异步与多次调用
......
class MyPromise{
......
// 定义实例属性
#handlers = []
constructor(func) {
const resolve = (result) => {
if(this.state === PENDING) {
......
// 调用成功回调
this.#handlers.forEach(({onFulfilled}) => {
onFulfilled(this.result)
})
}
}
const reject = (result) => {
if(this.state === PENDING) {
......
// 调用失败回调
this.#handlers.forEach(({onRejected}) => {
onRejected(this.result)
})
}
}
// 执行回调函数
func(resolve,reject)
}
then(onFulfilled,onRejected) {
......
// 执行回调
if(this.state === FULFILLED) {
onFulfilled(this.result)
} else if (this.state === REJECTED) {
onRejected(this.result)
} else if (this.state === PENDING) {
// 保存回调函数 等待resolve()或reject()执行
this.#handlers.push({
onFulfilled,onRejected
})
}
}
}
1.4 异步任务
封装异步任务函数:
// 封装函数
function runAsynctask(callback) {
if(typeof queueMicrotask === 'function') {
queueMicrotask(callback)
} else if (typeof MutationObserver === 'function') {
const obs = new MutationObserver(callback)
const divNode = document.createElement('div')
obs.observe(divNode,{childList:true})
divNode.innerText = 'huihui'
} else {
setTimeout(callback,0)
}
}
......
class MyPromise{
......
then(onFulfilled,onRejected) {
......
// 执行回调
if(this.state === FULFILLED) {
runAsynctask(() => {
onFulfilled(this.result)
})
} else if (this.state === REJECTED) {
runAsynctask(() => {
onRejected(this.result)
})
} else if (this.state === PENDING) {
this.#handlers.push({
onFulfilled:() => {
runAsynctask(() => {
onFulfilled(this.result)
})
},onRejected:() => {
runAsynctask(() => {
onRejected(this.result)
})
}
})
}
}
}
1.5 链式编程
1.5.1 处理异常/普通内容
then(onFulfilled,onRejected) {
// 判断
...
// 返回promise实例
const p = new MyPromise((resolve,reject) => {
if(this.state === FULFILLED) {
runAsynctask(() => {
try {
const x = onFulfilled(this.result)
resolve(x)
} catch(error) {
reject(error)
}
})
} else if (this.state === REJECTED) {
...
} else if (this.state === PENDING) {
...
}
})
return p
}
1.5.2 处理返回promise
if(this.state === FULFILLED) {
runAsynctask(() => {
try {
const x = onFulfilled(this.result)
// 返回promise
if (x instanceof MyPromise) {
x.then(res => resolve(res),err => reject(err))
} else {
resolve(x)
}
} catch(error) {
reject(error)
}
})
}
1.5.3 处理重复引用
if(this.state === FULFILLED) {
runAsynctask(() => {
try {
const x = onFulfilled(this.result)
// 处理重复引用
if (x === p) {
// 抛出错误
throw new TypeError('Chaining cycle detected for promise #<Promise>')
}
......
}
})
}
1.5.4 rejected状态
//抽取函数
function resolvePromise(p,x,resolve,reject) {
if(x === p) {
throw new TypeError('Chaining cycle detected for promise #<Promise>')
}
if (x instanceof MyPromise) {
x.then(res => resolve(res), err => reject(err))
} else {
resolve(x)
}
}
if(this.state === FULFILLED) {
runAsynctask(() => {
try {
const x = onFulfilled(this.result)
// 调用函数
resolvePromise(p, x, resolve, reject)
} catch(error) {
reject(error)
}
})
} else if (this.state === REJECTED) {
runAsynctask(() => {
const x = onRejected(this.result)
// 调用函数
resolvePromise(p,x,resolve,reject)
})
}
1.5.5 pending状态
else if (this.state === PENDING) {
this.#handlers.push({
onFulfilled:() => {
runAsynctask(() => {
try {
const x = onFulfilled(this.result)
resolvePromise(p,x,resolve,reject)
} catch (error) {
reject(error)
}
})
},onRejected:() => {
runAsynctask(() => {
try {
const x = onRejected(this.result)
resolvePromise(p,x,resolve,reject)
} catch (error) {
reject(error)
}
})
}
})
}
1.6 实例方法
1.6.1 catch方法
class MyPromise{
......
constructor(func) { ...... }
then(onFulfilled,onRejected) { ...... }
catch(onRejected) {
return this.then(undefined,onRejected)
}
}
1.6.2 finally方法
class MyPromise{
......
constructor(func) { ...... }
then(onFulfilled,onRejected) { ...... }
catch(onRejected) {...... }
finally(onFinally) {
return this.then(onFinally,onFinally)
}
}
1.7 静态方法
1.7.1 resolve 方法
// resolve方法返回已完成状态的promise对象
static resolve(value) {
if(value instanceof MyPromise) {
return value
}
return new MyPromise((resolve) => {
resolve(value)
})
}
1.7.2 reject 方法
// 返回rejected状态的Promise
static reject(value) {
return new MyPromise((undefined, reject) => {
reject(value)
})
}
1.7.3 race方法
// race方法等待任意一个请求完成后进行响应
static race(promises) {
return new MyPromise((resolve,reject) => {
// 判断是否是数组
if(!Array.isArray(promises)) {
return reject(new TypeError('Argument is not iterable'))
}
promises.forEach(p => {
MyPromise.resolve(p).then(res => { resolve(res) },err => { reject(err) })
})
})
}
1.7.4 all方法
static all(promises) {
return new MyPromise((resolve,reject) => {
if(!Array.isArray(promises)) {
return reject(new TypeError('Argument is not iterable'))
}
promises.length === 0 && resolve(promises)
const results = []
let count = 0
promises.forEach((p,index) => {
MyPromise.resolve(p).then(res => {
results[index] = res
count++
// 处理所有兑现
count === promises.length && resolve(results)
},err => {
// 处理第一个拒绝
reject(err)
})
})
})
}
1.7.5 allSettled方法
// allSettled方法返回promise状态全部敲定的结果
static allSettled(promises) {
return new MyPromise((resolve,reject) => {
if(!Array.isArray(promises)) {
return reject(new TypeError('Argument is not iterable'))
}
promises.length === 0 && resolve(promises)
// 等待全部敲定
const results = []
let count = 0
promises.forEach((p,index) => {
MyPromise.resolve(p).then(res => {
results[index] = {status:FULFILLED,value:res}
count++
count === promises.length && resolve(results)
},err => {
results[index] = {status:REJECTED,reason:err}
count++
count === promises.length && resolve(results)
})
})
})
}
1.7.6 any 方法
static any(promises) {
return new MyPromise((resolve,reject) => {
if(!Array.isArray(promises)){
return reject(new TypeError('Argument is not iterable'))
}
promises.length === 0 && reject(new AggregateError(promises, 'All promises were rejected'))
const errors = []
let count = 0
promises.forEach((p,index) => {
MyPromise.resolve(p).then(res => {
// 第一个兑现
resolve(res)
},err => {
// 全部拒绝
errors[index] = err
count++
count === promises.length && reject(new AggregateError(errors, 'All promises were rejected'))
})
})
})
}
2. 完整写法
// 封装函数
function runAsynctask(callback) {
if(typeof queueMicrotask === 'function') {
queueMicrotask(callback)
} else if (typeof MutationObserver === 'function') {
const obs = new MutationObserver(callback)
const divNode = document.createElement('div')
obs.observe(divNode,{childList:true})
divNode.innerText = 'huihui'
} else {
setTimeout(callback,0)
}
}
// 抽取函数
function resolvePromise(p, x, resolve, reject) {
if (x === p) {
throw new TypeError('Chaining cycle detected for promise #<Promise>')
}
if (x instanceof MyPromise) {
x.then(res => resolve(res), err => reject(err))
} else {
resolve(x)
}
}
// 状态
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise{
// 添加状态/原因
state = PENDING
result = undefined
// 定义实例属性
#handlers = []
constructor(func) {
// 修改状态pending -> fulfilled/rejected
const resolve = (result) => {
if(this.state === PENDING) {
this.state = FULFILLED
this.result = result
// 调用成功回调
this.#handlers.forEach(({onFulfilled}) => {
onFulfilled(this.result)
})
}
}
const reject = (result) => {
if(this.state === PENDING) {
this.state = REJECTED
this.result = result
// 调用失败回调
this.#handlers.forEach(({onRejected}) => {
onRejected(this.result)
})
}
}
// 执行回调函数
func(resolve,reject)
}
then(onFulfilled,onRejected) {
// 判断
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : x => x
onRejected = typeof onRejected === 'function' ? onRejected : x => { throw x }
// 返回promise实例
const p = new MyPromise((resolve,reject) => {
if(this.state === FULFILLED) {
runAsynctask(() => {
try {
const x = onFulfilled(this.result)
// 调用函数
resolvePromise(p, x, resolve, reject)
} catch(error) {
reject(error)
}
})
} else if (this.state === REJECTED) {
runAsynctask(() => {
const x = onRejected(this.result)
// 调用函数
resolvePromise(p,x,resolve,reject)
})
} else if (this.state === PENDING) {
this.#handlers.push({
onFulfilled:() => {
runAsynctask(() => {
try {
const x = onFulfilled(this.result)
resolvePromise(p,x,resolve,reject)
} catch (error) {
reject(error)
}
})
},onRejected:() => {
runAsynctask(() => {
try {
const x = onRejected(this.result)
resolvePromise(p,x,resolve,reject)
} catch (error) {
reject(error)
}
})
}
})
}
})
return p
}
catch(onRejected) {
return this.then(undefined,onRejected)
}
finally(onFinally) {
return this.then(onFinally,onFinally)
}
// resolve方法返回已完成状态的promise对象
static resolve(value) {
if(value instanceof MyPromise) {
return value
}
return new MyPromise((resolve) => {
resolve(value)
})
}
// 返回rejected状态的Promise
static reject(value) {
return new MyPromise((undefined, reject) => {
reject(value)
})
}
// race方法等待任意一个请求完成后进行响应
static race(promises) {
return new MyPromise((resolve,reject) => {
// 判断是否是数组
if(!Array.isArray(promises)) {
return reject(new TypeError('Argument is not iterable'))
}
promises.forEach(p => {
MyPromise.resolve(p).then(res => { resolve(res) },err => { reject(err) })
})
})
}
static all(promises) {
return new MyPromise((resolve,reject) => {
if(!Array.isArray(promises)) {
return reject(new TypeError('Argument is not iterable'))
}
promises.length === 0 && resolve(promises)
const results = []
let count = 0
promises.forEach((p,index) => {
MyPromise.resolve(p).then(res => {
results[index] = res
count++
// 处理所有兑现
count === promises.length && resolve(results)
},err => {
// 处理第一个拒绝
reject(err)
})
})
})
}
// allSettled方法返回promise状态全部敲定的结果
static allSettled(promises) {
return new MyPromise((resolve,reject) => {
if(!Array.isArray(promises)) {
return reject(new TypeError('Argument is not iterable'))
}
promises.length === 0 && resolve(promises)
// 等待全部敲定
const results = []
let count = 0
promises.forEach((p,index) => {
MyPromise.resolve(p).then(res => {
results[index] = {status:FULFILLED,value:res}
count++
count === promises.length && resolve(results)
},err => {
results[index] = {status:REJECTED,reason:err}
count++
count === promises.length && resolve(results)
})
})
})
}
static any(promises) {
return new MyPromise((resolve,reject) => {
if(!Array.isArray(promises)){
return reject(new TypeError('Argument is not iterable'))
}
promises.length === 0 && reject(new AggregateError(promises, 'All promises were rejected'))
const errors = []
let count = 0
promises.forEach((p,index) => {
MyPromise.resolve(p).then(res => {
// 第一个兑现
resolve(res)
},err => {
// 全部拒绝
errors[index] = err
count++
count === promises.length && reject(new AggregateError(errors, 'All promises were rejected'))
})
})
})
}
}