1 Promise语法
//resolve reject
const promise = new Promise((resolve,reject) => {
// 异步操作代码
if ( /* 操作成功 */){
resolve("success");
}else{
reject("error");
}
})
//then catch
promise.then(res => {
console.log(res);
}, err => {
console.log(err );
}).catch(function(e){
console.log(e);
})
const p1 = Promise.resolve(1)
const p2 = Promise.reject(2)
function p3(){
return new Promise(function(resolve,reject){
resolve("3");
})
}
//all方法提供了并行执行异步操作的能力,在all中所有异步操作结束后执行回调。
Promise.all([p1,p2,p3()]).then(function(data){
console.log(data); //[1,2,'3']
})
//race 第一个promise返回的结果
Promise.race([p1,p2,p3()]).then(function(data){
console.log(data); //1
})
//any 第一个resolve返回的而己过
Promise.any([p1,p2,p3()]).then(function(data){
console.log(data); //1
})
2 Promise原理
2.1 构造函数
- 定义类
MyPromise
,内部添加构造函数constructor
,构造函数需要接收回调函数func
- 在构造函数中定义
resolve
和reject
- 构造函数内部调用
func
并将resolve
和reject
传入:func(resolve,reject)
// 1. 定义类 class MyPromise { // 2. 添加构造函数 constructor(func) { // 3. 定义resolve/reject const resolve = (result) => { console.log('resolve-执行啦:', result) } const reject = (result) => { console.log('reject-执行啦:', result) } // 4. 执行回调函数 func(resolve, reject) } } //调用 const p = new MyPromise((resolve, reject) => { resolve('success') // reject('error') })
2.2 状态
- 定义3个常量用来保存状态,
pending
,fulfilled
,rejected
MyPromise
内部定义属性state
和result
分别用来保存状态和原因- 调用
resolve
时传入具体原因,如果状态为pending
则更改状态并记录兑现原因 - 调用
reject
时传入具体原因,如果状态为pending
则更改状态并记录拒绝原因const PENDING = 'pending' const FULFILLED = 'fulfilled' const REJECTED = 'rejected' class MyPromise { // 1. 添加状态 state = PENDING // 2. 添加原因 result = undefined constructor(func) { // 3. 调整resolve/reject // 4. 状态不可逆 // 改状态: pending->fulfilled // 记录原因 const resolve = (result) => { if (this.state === PENDING) { this.state = FULFILLED this.result = result } } // 改状态: pending->rejected // 记录原因 const reject = (result) => { if (this.state === PENDING) { this.state = REJECTED this.result = result } } func(resolve, reject) } } //调用 const p = new MyPromise((resolve, reject) => { resolve('success') // pending -> fulfilled // reject('error') // pending -> rejected }) p.state // 状态 p.result // 原因
2.3 then方法
-
添加
then
方法,接收2个回调函数- 成功回调
onFulfilled
- 失败回调
onRejected
- 成功回调
-
判断传入的
onFulfilled
和onRejected
是否为函数,如果不是设置默认值 -
根据状态调用
onFulfilled
或onRejected
并传入兑现或拒绝原因const PENDING = 'pending' const FULFILLED = 'fulfilled' const REJECTED = 'rejected' class MyPromise { // 状态 state = PENDING // 原因 result = undefined // 构造函数 constructor(func) { // pending->fulfilled const resolve = (result) => { if (this.state === PENDING) { this.state = FULFILLED this.result = result } } // pending->rejected const reject = (result) => { if (this.state === PENDING) { this.state = REJECTED this.result = result } } func(resolve, reject) } // 1. 添加实例方法 then(onFulfilled, onRejected) { // 2. 参数判断(参考文档) onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : x => x onRejected = typeof onRejected === 'function' ? onRejected : x => { throw x } // 2.1 执行成功回调 // 2.2 执行失败回调 if (this.state === FULFILLED) { onFulfilled(this.result) } else if (this.state === REJECTED) { onRejected(this.result) } } } //调用 const p = new MyPromise((resolve, reject) => { resolve('success') // reject('error') }) p.then(res => { console.log('成功回调:', res) }, err => { console.log('失败回调:', err) })
2.4 then方法 - 异步
-
MyPromise
添加私有属性#handlers
- 保存then方法调用时状态为
pending
的回调函数 - 格式为对象数组:
[{onFulfilled,onRejected}...]
- 保存then方法调用时状态为
-
构造函数内部调整
resolve
和reject
的逻辑- 调用
resolve
时取出数组#handlers
中的所有onFulfilled
回调函数进行调用 - 调用
reject
时取出数组#handlers
中的所有onRejected
回调函数进行调用
const PENDING = 'pending' const FULFILLED = 'fulfilled' const REJECTED = 'rejected' class MyPromise { // 状态 state = PENDING // 原因 result = undefined // 1. 定义实例属性 #handlers = [] // [{onFulfilled,onRejected}...] // 构造函数 constructor(func) { // pending->fulfilled const resolve = (result) => { if (this.state === PENDING) { this.state = FULFILLED this.result = result // 3. 调用成功回调 this.#handlers.forEach(({ onFulfilled }) => { onFulfilled(this.result) }) } } // pending->rejected const reject = (result) => { if (this.state === PENDING) { this.state = REJECTED this.result = result // 4. 调用失败回调 this.#handlers.forEach(({ onRejected }) => { onRejected(this.result) }) } } func(resolve, reject) } // then方法 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) } else if (this.state === PENDING) { // 2. 保存回调函数 this.#handlers.push({ onFulfilled, onRejected }) } } } //调用 const p = new MyPromise((resolve, reject) => { setTimeout(() => { resolve('success') // reject('error') }, 2000); }) p.then(res => { console.log('then1:', res) }, err => { console.log('then1:', err) }) p.then(res => { console.log('then2:', res) }, err => { console.log('then2:', err) })
- 调用
2.5 异步任务
vue2异步方法:Promise.then、MutationObserver 、 setImmediate 、 setTimeout
选用:queueMicrotask 、MutationObserver 、setTimeout
1. queueMicrotask
:新式浏览器均支持,node11开始支持,ie不支持
2. MutationObserver
:新式浏览器均支持,ie11开始支持
3. setImmediate
:新式浏览器只有edge支持,ie10开始支持
4. setTimeout
:浏览器支持,node支持
核心步骤:
- 封装执行异步任务的函数
- 定义函数传入异步任务(回调函数)
- 内部根据实际情况判断并使用开启异步任务的api即可,比如
queueMicrotask
,MutationObserver
- 调用的
api
可以根据实际情况进行调整 - 如果都无法执行,使用
setTimeout
兜底
- 调整
then
中的逻辑,fulFilled
,rejected
,pending
3种状态时的回调函数,使用封装的函数包装一次
// 1. 定义异步任务函数
function runAsynctask(callback) {
// 2. 调用核心api(queueMicrotask,MutationObserver,setTimeout)
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 = '12345'
} else {
setTimeout(callback, 0)
}
}
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise {
// 状态
state = PENDING
// 原因
result = undefined
// 回调函数数组
#handlers = [] // [{onFulfilled,onRejected}...]
// 构造函数
constructor(func) {
// pending->fulfilled
const resolve = (result) => {
if (this.state === PENDING) {
this.state = FULFILLED
this.result = result
this.#handlers.forEach(({ onFulfilled }) => {
onFulfilled(this.result)
})
}
}
// pending->rejected
const reject = (result) => {
if (this.state === PENDING) {
this.state = REJECTED
this.result = result
this.#handlers.forEach(({ onRejected }) => {
onRejected(this.result)
})
}
}
func(resolve, reject)
}
// then方法
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : x => x
onRejected = typeof onRejected === 'function' ? onRejected : x => { throw x }
// 3. 使用封装函数
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)
})
}
})
}
}
}
2.6 链式编程-fulfilled状态-返回值+异常
需求:
-
then
的链式编程 -
目前只考虑
then
的第一个回调函数- 返回普通值
- 内部出现异常
const p = new MyPromise ((resolve, reject) => { resolve(1) }) p.then(res => { console.log(res) // throw 'throw-error' return 2 }).then(res => { console.log(res) }, err => { console.log(err) })
核心步骤
-
链式编程的本质then方法会返回一个新的
MyPromise
对象 -
将原本的代码迁移到返回的
MyPromise
对象的回调函数中 -
内部通过
try-catch
捕获异常,出现异常通过reject
传递异常 -
获取
onFulfilled
的执行结果,并通过resolve
传递// 执行异步任务 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 = '12345' } else { setTimeout(callback, 0) } } const PENDING = 'pending' const FULFILLED = 'fulfilled' const REJECTED = 'rejected' class MyPromise { // 状态 state = PENDING // 原因 result = undefined // 回调函数数组 #handlers = [] // [{onFulfilled,onRejected}...] // 构造函数 constructor(func) { // pending->fulfilled const resolve = (result) => { if (this.state === PENDING) { this.state = FULFILLED this.result = result this.#handlers.forEach(({ onFulfilled }) => { onFulfilled(this.result) }) } } // pending->rejected 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 } // 1. 返回新Promise实例 const p2 = new MyPromise ((resolve, reject) => { if (this.state === FULFILLED) { runAsynctask(() => { // 2. 获取返回值 try { const x = onFulfilled(this.result) // console.log('x:', x) // 2.1 处理返回值 resolve(x) } catch (error) { // 2.2 处理异常 // console.log('捕获异常:', error) reject(error) } }) } 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) }) } }) } }) return p2 } }
2.7 链式编程-fulfilled状态-返回Promise
需求:
then
的链式编程- 目前只考虑
then
的第一个回调函数- 返回
Promise
const p = new MyPromise((resolve, reject) => { resolve(1) }) p.then(res => { return new MyPromise((resolve, reject) => { resolve(2) // reject('error') }) }).then(res => { console.log('p2:', res) // 2 }, err => { console.log('p2:', err) // error })
- 返回
核心步骤:
- 判断
onFulfilled
的执行结果是否为MyPromise
实例 - 如果是的话调用返回值的
then
方法,获取兑现和拒绝的原因并通过resolve
和reject
传递即可// 执行异步任务 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 = '12345' } else { setTimeout(callback, 0) } } const PENDING = 'pending' const FULFILLED = 'fulfilled' const REJECTED = 'rejected' class MyPromise { // 状态 state = PENDING // 原因 result = undefined // 回调函数数组 #handlers = [] // [{onFulfilled,onRejected}...] // 构造函数 constructor(func) { // pending->fulfilled const resolve = (result) => { if (this.state === PENDING) { this.state = FULFILLED this.result = result this.#handlers.forEach(({ onFulfilled }) => { onFulfilled(this.result) }) } } // pending->rejected const reject = (result) => { if (this.state === PENDING) { this.state = REJECTED this.result = result this.#handlers.forEach(({ onRejected }) => { onRejected(this.result) }) } } func(resolve, reject) } // then方法 then(onFulfilled, onRejected) { onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : x => x onRejected = typeof onRejected === 'function' ? onRejected : x => { throw x } const p2 = new MyPromise((resolve, reject) => { if (this.state === FULFILLED) { runAsynctask(() => { try { const x = onFulfilled(this.result) // 1.处理返回Promise if (x instanceof MyPromise) { // console.log('MyPromise实例') // 2. 调用then方法 // x.then(res => console.log(res), err => console.log(err)) x.then(res => resolve(res), err => reject(err)) } else { resolve(x) } } catch (error) { reject(error) } }) } 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) }) } }) } }) return p2 } }
2.8 链式编程-fulfilled状态-重复引用
需求:
then
中返回的then
方法返回的Promise
实例报错const p = new MyPromise((resolve, reject) => { resolve(1) }) const p2 = p.then(res => { return p2 }) p2.then( res => { }, err => console.log('err:', err))
核心步骤:
- 判断
onFulfilled
函数的返回值是否和then
方法内部返回的MyPromise
相同 - 如果相同抛出错误
new TypeError('Chaining cycle detected for promise #<Promise>')
// 执行异步任务 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 = '12345' } else { setTimeout(callback, 0) } } const PENDING = 'pending' const FULFILLED = 'fulfilled' const REJECTED = 'rejected' class MyPromise { // 状态 state = PENDING // 原因 result = undefined // 回调函数数组 #handlers = [] // [{onFulfilled,onRejected}...] // 构造函数 constructor(func) { // pending->fulfilled const resolve = (result) => { if (this.state === PENDING) { this.state = FULFILLED this.result = result this.#handlers.forEach(({ onFulfilled }) => { onFulfilled(this.result) }) } } // pending->rejected const reject = (result) => { if (this.state === PENDING) { this.state = REJECTED this.result = result this.#handlers.forEach(({ onRejected }) => { onRejected(this.result) }) } } func(resolve, reject) } // then方法 then(onFulfilled, onRejected) { onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : x => x onRejected = typeof onRejected === 'function' ? onRejected : x => { throw x } const p2 = new MyPromise((resolve, reject) => { if (this.state === FULFILLED) { runAsynctask(() => { try { const x = onFulfilled(this.result) // 1. 处理重复引用 if (x === p2) { // console.log('返回了p2') // 2. 抛出错误 Chaining cycle detected for promise #<Promise> throw new TypeError('Chaining cycle detected for promise #<Promise>') } if (x instanceof MyPromise) { x.then(res => resolve(res), err => reject(err)) } else { resolve(x) } } catch (error) { reject(error) } }) } 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) }) } }) } }) return p2 } }
2.9 链式编程-rejected状态 pending状态
需求:
then
的第二个回调函数,执行reject
时的链式编程then
方法中pending
状态时推入数组的函数增加try-catch
捕获异常- 获取推入数组的回调函数的返回值
- 调用封装的函数并传入获取的值
const p = new MyPromise((resolve, reject) => { reject(1) // setTimeout(() => { // resolve(1) // }, 2000) }) const p2 = p.then(undefined, err => { throw 'error' // return p2 // return 2 // return new MyPromise((resolve, reject) => { // resolve('MyPromise-2') // }) }) p2.then(res => { console.log('p2-res:', res) }, err => { console.log('p2-err:', err) })
核心步骤:
-
判断
onRejected
可能出现的异常,如果出现通过reject
传递 -
获取
onRejected
函数的执行结果 -
将
fulfilled
状态时的处理逻辑抽取为函数,rejected
状态时调用函数复用逻辑// 执行异步任务 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 = '12345' } else { setTimeout(callback, 0) } } const PENDING = 'pending' const FULFILLED = 'fulfilled' const REJECTED = 'rejected' class MyPromise { // 状态 state = PENDING // 原因 result = undefined // 回调函数数组 #handlers = [] // [{onFulfilled,onRejected}...] // 构造函数 constructor(func) { // pending->fulfilled const resolve = (result) => { if (this.state === PENDING) { this.state = FULFILLED this.result = result this.#handlers.forEach(({ onFulfilled }) => { onFulfilled(this.result) }) } } // pending->rejected 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 } const p2 = new MyPromise((resolve, reject) => { if (this.state === FULFILLED) { runAsynctask(() => { try { const x = onFulfilled(this.result) // 4. 调用函数 resolvePromise(p2, x, resolve, reject) // if (x === p2) { // throw new TypeError('Chaining cycle detected for promise #<Promise>') // } // if (x instanceof MyPromise) { // x.then(res => resolve(res), err => reject(err)) // } else { // resolve(x) // } } catch (error) { reject(error) } }) } else if (this.state === REJECTED) { runAsynctask(() => { // 1. 处理异常 try { // 2. 获取返回值 const x = onRejected(this.result) // console.log('x:', x) // 4. 调用函数 resolvePromise(p2, x, resolve, reject) } catch (error) { reject(error) } }) } else if (this.state === PENDING) { this.#handlers.push({ onFulfilled: () => { runAsynctask(() => { // 1. 处理异常 try { // 2.获取返回值 const x = onFulfilled(this.result) // 4.调用函数 resolvePromise(p2, x, resolve, reject) } catch (error) { reject(error) } }) }, onRejected: () => { runAsynctask(() => { // 1. 处理异常 try { // 2.获取返回值 const x = onRejected(this.result) // 4.调用函数 resolvePromise(p2, x, resolve, reject) } catch (error) { reject(error) } }) } }) } }) return p2 } } // 3.抽取函数 function resolvePromise(p2, x, resolve, reject) { if (x === p2) { throw new TypeError('Chaining cycle detected for promise #<Promise>') } if (x instanceof MyPromise) { x.then(res => resolve(res), err => reject(err)) } else { resolve(x) } }
2.10 实例方法catch
需求
const p = new MyPromise((resolve, reject) => {
reject('reject-error')
// throw 'throw-error'
})
p.then(res => {
console.log('res:', res)
}).catch(err => {
console.log('err:', err)
})
核心步骤
-
定义
catch
方法,等同于:then(undefined,onRjected)
-
使用
try-catch
包裹constructor
中的func
捕获异常// 构造函数 constructor(func) { // pending->fulfilled const resolve = (result) => { if (this.state === PENDING) { this.state = FULFILLED this.result = result this.#handlers.forEach(({ onFulfilled }) => { onFulfilled(this.result) }) } } // pending->rejected const reject = (result) => { if (this.state === PENDING) { this.state = REJECTED this.result = result this.#handlers.forEach(({ onRejected }) => { onRejected(this.result) }) } } // 2. 处理异常 try { func(resolve, reject) } catch (error) { // console.log('error:', error) reject(error) } } catch(onRejected) { // 1. 内部调用then方法 return this.then(undefined, onRejected) }
2.11 实例方法finally
需求:
- 无论成功失败都会执行
finally
的回调函数 - 回调函数不接受任何参数
const p = new MyPromise((resolve, reject) => { // resolve('resolve-res') // reject('reject-error') // throw 'throw-error' }) p.then(res => { console.log('res:', res) }).catch(err => { console.log('err:', err) }).finally(() => { console.log('finally') })
核心步骤
- 添加
finally
方法,接收最终执行的回调函数onFinally
finally
方法的本质为内部调用then
方法- 调用形式为第一个和第二个回调函数均传入
onFinally
即可finally(onFinally) { return this.then(onFinally,onFinally) }
2.12 静态方法resolve
需求
返回一个带有成功原因的Promise
对象
MyPromise.resolve(new MyPromise((resolve, reject) => {
// resolve('resolve')
// reject('reject')
// throw 'error'
})).then(res => {
console.log('res:', res)
}, err => {
console.log('err:', err)
})
MyPromise.resolve('xdk').then(res => {
console.log(res)
})
核心步骤:
- 通过
static
关键字添加静态方法resolve
,接收参数value
- 内部判断传入的值
- 如果是
Promise
实例,直接返回 - 其他的值,创建
Promise
实例并返回,内部通过resolve(value)
传递value
static resolve(value) { // 1. 判断传入值 if (value instanceof MyPromise) { // 2.1 Promise直接返回 return value } // 2.2 转为Promise并返回(fulfilled状态) return new MyPromise((resolve) => { resolve(value) }) }
- 如果是
2.13 静态方法reject
需求:
返回一个带有拒绝原因的Promise
对象
MyPromise.reject('error').catch(res => {
console.log(res)
})
核心步骤:
- 添加静态方法
reject
并接收参数value
- 内部返回一个拒绝状态的
Promise
实例即可
static reject(value) {
// 1. 返回rejected状态的Promise
// new MyPromise((resolve,reject)=>{
return new MyPromise((undefined, reject) => {
reject(value)
})
}
2.14 静态方法race
需求:
- 接收Promise数组,数组中第一个Promise敲定时,获取
成功/失败
结果 - 传入的参数不是数组,直接报错
const p1 = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve(1)
}, 2000)
})
const p2 = new MyPromise((resolve, reject) => {
setTimeout(() => {
reject(2)
}, 1000)
})
MyPromise.race([p1, p2, 'xdk']).then((res) => {
console.log('res:', res)
}, err => {
console.log('err:', err)
})
核心步骤:
- 添加静态方法
race
接收参数promises
- 内部返回一个新的
Promise
实例,在返回的Promise
实例中:- 判断参数是否为数组,不是通过
reject
传递错误 - 遍历Promise数组,通过
resolve
静态方法等待每一个兑现 - 任何一个兑现,调用
resolve
传递兑现结果 - 任何一个拒绝,调用
reject
传递拒绝原因
- 判断参数是否为数组,不是通过
static race(promises) {
// 1. 返回Promise
return new MyPromise((resolve, reject) => {
// 2. 判断是否为数组
if (!Array.isArray(promises)) {
return reject(new TypeError('Argument is not iterable'))
}
// 3. 等待第一个敲定
promises.forEach(p => {
// p.then
MyPromise.resolve(p).then(res => { resolve(res) }, err => { reject(err) })
})
})
}
2.15 静态方法all
需求:
接收Promise数组
- 所有Promise都成功时,返回一个成功的Promise对象及成功数组
- 任何一个Promise失败,返回一个失败的Promise对象及第一个失败原因
const p1 = MyPromise.resolve(1)
const p2 = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve(2)
// reject('error')
}, 1000)
})
const p3 = 3
MyPromise.all([p1, p2, p3]).then(res => {
console.log('res:', res)
}, err => {
console.log('err:', err)
})
核心步骤:
- 添加静态方法
all
- 内部返回
Promise
实例,在返回的Promise
实例中:- 判断参数是否为数组,不是通过
reject
传递错误 - 空数组直接以空数组为结果进行兑现
- 遍历
Promise
数组,通过resolve
静态方法等待结果- 处理全部兑现:
- 通过数组记录结果,用索引的方式来添加,目的是保证结果的顺序和
Promise
数组的顺序一致 - 通过兑现次数进行判断,因为是通过索引的方式记录结果,如果第一次兑现的是最后一个,那么数组的长度就已经和Promise数组的长度一致了,所以需要通过兑现次数来进行判断
- 通过数组记录结果,用索引的方式来添加,目的是保证结果的顺序和
- 任意一个拒绝,调用
reject
传递拒绝原因
- 处理全部兑现:
- 判断参数是否为数组,不是通过
static all(promises) {
// 1. 返回Promise实例
return new MyPromise((resolve, reject) => {
// 2. 判断是否为数组
if (!Array.isArray(promises)) {
return reject(new TypeError('Argument is not iterable'))
}
// 3. 空数组直接兑现
promises.length === 0 && resolve(promises)
// 4.1 记录结果
const results = []
let count = 0
promises.forEach((p, index) => {
MyPromise.resolve(p).then(res => {
// results.push 无法保证 结果的顺序和Promise数组的顺序一致
// index 和 Promise实例的索引一致,保证顺序
results[index] = res
// 4.2 判断全部兑现
count++
count === promises.length && resolve(results)
}, err => {
// 5. 处理第一个拒绝
reject(err)
})
})
})
}
2.16 静态方法allSettled
需求:
- 传入
Promise
数组,当所有对象都已敲定时 - 返回一个新的
Promise
对象及以数组形式保存的结果
const p1 = MyPromise.resolve(1)
const p2 = 2
const p3 = new MyPromise((resolve, reject) => {
setTimeout(() => {
reject(3)
}, 1000)
})
MyPromise.allSettled([p1, p2, p3]).then(res => {
console.log('res:', res)
}, err => {
console.log('err:', err)
})
核心步骤:
- 添加静态方法
allSettled
- 内部返回
Promise
实例,在返回的Promise
实例中:- 判断参数是否为数组,不是通过
reject
传递错误 - 空数组直接以空数组为结果进行兑现
- 判断参数是否为数组,不是通过
- 遍历
Promise
数组,通过resolve
静态方法等待敲定结果 - 等待全部敲定:并记录结果,根据兑现和拒绝将如下格式的内容通过索引的方式的记录到数组中
- 处理兑现:
{state:FULFILLED,value:'xxx'}
- 处理拒绝:
{state:REJECTED,reason:'xxx'}
- 处理兑现:
- 根据敲定的次数判断是否全部敲定,全部敲定之后,通过
resolve
传递结果数组
static allSettled(promises) {
// 1. 返回Promise
return new MyPromise((resolve, reject) => {
// 2. 数组判断
if (!Array.isArray(promises)) {
return reject(new TypeError('Argument is not iterable'))
}
// 3. 为空直接敲定
promises.length === 0 && resolve(promises)
// 4. 等待全部敲定
// 4.1 记录结果
const results = []
let count = 0
promises.forEach((p, index) => {
MyPromise.resolve(p).then(res => {
// 4.2 处理兑现{status:'fulfilled',value:''}
results[index] = { status: FULFILLED, value: res }
count++
count === promises.length && resolve(results)
}, err => {
// 4.3 处理拒绝{status:'rejected',reason:''}
results[index] = { status: REJECTED, reason: err }
count++
count === promises.length && resolve(results)
})
})
})
}
2.17 静态方法any
需求:
传入Promise
数组,
- 任何一个
Promise
对象敲定时,返回一个新的Promise
对象,及对应的结果 - 所有Promise都被拒绝时,返回一个包含所有拒绝原因的
AggregateError
错误数组
const p1 = new MyPromise((resolve, reject) => {
setTimeout(() => {
reject(1)
}, 2000)
})
const p2 = 2
const p3 = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve(3)
// reject(3)
}, 1000)
})
MyPromise.any([p1, p2, p3]).then(res => {
console.log('res:', res)
}, err => {
console.dir(err)
})
核心步骤:
- 添加静态方法
any
- 内部返回
Promise
实例,在返回的Promise
实例中:- 判断参数是否为数组,不是通过
reject
传递错误 - 空数组直接以空数组为结果进行兑现
- 判断参数是否为数组,不是通过
- 遍历
Promise
数组,通过resolve
静态方法等待结果- 第一个兑现,通过
resolve
传递兑现结果 - 全部拒绝:
- 定义数组,保存拒绝原因,通过索引记录,目的是保证顺序和
Promise
数组一致 - 通过次数判断是否全部拒绝,当全部拒绝时,通过
reject
传递AggregateError
类型的错误,并将拒绝原因数组传递进去即可
- 定义数组,保存拒绝原因,通过索引记录,目的是保证顺序和
- 第一个兑现,通过
static any(promises) {
// 1. 返回Promise,数组判断
return new MyPromise((resolve, reject) => {
if (!Array.isArray(promises)) {
return reject(new TypeError('Argument is not iterable'))
}
// 2. 空数组直接拒绝
promises.length === 0 && reject(new AggregateError(promises, 'All promises were rejected'))
// 3. 等待结果
const errors = []
let count = 0
promises.forEach((p, index) => {
MyPromise.resolve(p).then(res => {
// 3.1 第一个兑现
resolve(res)
}, err => {
// 3.2 全部拒绝
errors[index] = err
count++
count === promises.length && reject(new AggregateError(errors, 'All promises were rejected'))
})
})
})
}
2.18 Promise\A+规范
-
Promise\A+
是社区推出的规范,最早Promise也是社区推出并实现的,旨在规范Promise
的实现,里面约定了:- 状态必须是
pending
,fulfilled
,rejected
then
方法的详细实现细节- 各种边界情况…
- 状态必须是
-
早期使用
Promise
需要导入第三方库,现在在新式浏览器中已经不需要导入第三方库,因为Promise
是默认开启的 -
无论是早期实现了Promise的第三方库,以及现在的新式浏览器内置的Promise,都是符合
Promise\A+
规范要求的