Promise的使用
异步任务的处理
在学习promise之前,我们先来了解一下异步任务的处理,从一个实际的例子作为切入点:
- 我们调用一个函数,这个函数中发送网络请求(我们可以用定时器来模拟)
- 如果发送网络请求成功了,那么告知调用者发送成功,并且返回成功相关的数据
- 如果发送网络请求失败了,那么告知调用者发送失败,并且返回失败报告
解决方案如下:
function requestData(url,successCallback,failureCallback){
setTimeout(()=>{
if(url === 'https://www.baidu.com'){
successCallback("一组成功数据")
// 发送成功执行
}else{
failureCallback("失败报告")
//发送失败执行
},1000)
function successCallback(res){
console.log(res)
}
function failureCallback(err){
console.log(err)
}
上面解决的方案中,我们可以解决请求函数得到结果后,获取对应的回调,但他存在两个主要的问题
- 第一:我们需要自己设计回调函数、回调函数的名称、回调函数的使用
- 第二:队医不同的人、不同的框架设计出来的方案是不同的,那么我们必须耐下心来看别人的源码或者文档,一边可以理解他这个函数怎么使用
ES6之后,ECMA推出了promise,提供统一的API接口,用来实现异步任务的处理
promise和promise的API
promise是一个类,可以翻译成承诺、许诺- 当我们需要给予到用着一个承诺:待会我给你回调数据时,就可以创建一个Pormise的对象
- 通过new创建
promise对象时,我们需要传入一个回调函数,我们成为executor- 这个回调函数会立即执行,并且回调函数有两个参数同样也是回调函数
resolve、reject - 当我们调用
resolve回调函数的时候,就会执行Promise对象中的then方法传入的回调函数 - 当我们调用
reject回调函数的时候,就会执行Promise对象中的catch方法传入的回调函数
- 这个回调函数会立即执行,并且回调函数有两个参数同样也是回调函数
Promise的代码结构
const promise = new Promise((resolve,reject)=>{
// 调用resolve,那么then传入的回调会被执行
resolve("成功数据")
// 调用reject,那么then传入的回调会被执行
reject("错误信息")
}
//写法一
// then方法传入的回调函数两个回调函数:
// > 第一个回调函数, 会在Promise执行resolve函数时, 被回调
// > 第二个回调函数, 会在Promise执行reject函数时, 被回调
promise.then(res=>{
console.log(res)
}).catch(err=>{
console.log(err)
})
//写法二
//catch方法传入的回调函数, 会在Promise执行reject函数时, 被回调
promise.then(res=>{
console.log(res)
},err=>{
console.log(err)
})
上面Promise使用过程中,我们可以将它划分为三个状态:
- 待定(pendding):初始状态,既没有对象,也没有拒绝,当执行
executor中的代码时,处于该状态 - 已兑现(fufilled):意味着操作成功完成,执行
resolve时,处于该状态 - 与拒绝(rejected):意味着操作失败,**执行
reject时,处于该状态
有了Promise,我们就可以将之前的代码进行重构了:
function requestData(url){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
if(url === "https://www.baidu.com"){
resolve("一组成功的数据")
}else{
reject("请求url错误")
}
},1000)
}
}
Executor
Executor是在创建Promise时需要传入的一个回调函数,这个回调函数会被立即执行,并传入两个参数:
new Promise((resolve,reject)=>{
console.log("111")
})
//打印台会输出 111
通常我们会在Executor中确定我们的Promise状态
- 通过
resolve,可以兑现(fufiled)Promise的状态,我们也可以称之为已决议(resolved) - 通过
reject,可以拒绝(reject)Promise的状态 注意:一旦状态确定下来,Promise的状态就会被锁死,该promise的状态是不可更改的 - 在我们调用
resolve的时候,如果resolve传入的值本身不是一个Promise,那么会将该Promise的状态变成兑(fulfilled) - 在之后我们去调用
reject时,已经不会有任何的响应了(并不是这行代码不会执行,而是无法改变Promise状态);
resolve不同值的区别
- 情况一:如果
resolve传入的传入一个普通值或者对象,那么这个值会作为then回调的参数 - 情况二:如果
resolve传入的传入一个Promise对象,那么这个新的Promise会决定原Promise的状态 - 情况三:如果
resolve传入的对象,并且对象有实现then方法,那么会执行then方法,并且根据then方法的结果决定Promise的状态
//resolve传入普通参数 pending->fufilled
const newPromise = new Promise((resolve, reject) => {
resolve("aaaaaa")
})
newPromise.then(res=>{
console.log(res) //aaaaaa
})
//resolve传入Promise对象
new Promise((resolve, reject) => {
// pending -> fulfilled
resolve(newPromise)
}).then(res => {
console.log("res:", res) //res: aaaaaa
})
//传入一个对象,这个对象有then方法
new Promise((resolve, reject) => {
// pending -> fulfilled
const obj = {
then: function(resolve, reject) {
// resolve("resolve message")
reject("reject message")
}
}
resolve(obj)
}).then(res => {
console.log("res:", res) // res : resolve message
}, err => {
console.log("err:", err) //err " reject message
})
then方法
then方法 - 接收两个参数
then方法时Promise对象上的一个方法:他其实是放在Promise的原型Peomise.prototype.then
then方法接收两个参数:
* fufilled的回调函数:当状态变为fufilled时会回调函数
* reject的回调函数:当状态变为reject时会回调函数
promise.then(res=>{
console.log(res)
},err=>{
console.log(err)
})
//等价于
promise.then(res=>{
console.log(res)
}}.catch(err=>{
console.log(err)
})
then方法 - 多次调用
一个Promise的then方法是可以被对此调用的:
* 每次调用我们都可以传入一个对应fufilled回调
* 当Promise的状态编程fufilled的时候,这些回调函数都会被执行
const promise = new Promise((resolve, reject) => {
resolve("hahaha")
})
promise.then(res=>{
console.log("res1":res) // res1 :hahaha
})
promise.then(res=>{
console.log("res2":res) // res2 :hahaha
})
promise.then(res=>{
console.log("res3":res) // res3 :hahaha
})
then方法 -返回值
then方法本身是有返回值的,它的返回值是一个Promise,所以我们可以进行链式调用,但是then方法返回的Promise到底处于什么样的状态呢?
- 当
then方法中的回调函数本身在执行的时候,那么它处于pending状态 - 当
then方法中的回调函数返回一个结果时,那么它处于fulfilled状态,并且会将结果作为resolve的参数- 情况一:返回一个普通值
- 情况二:返回一个Promise
- 情况三:返回一个thenable对象
- 当
then方法抛出一个异常时,那么它处于reject状态
catch方法
catch方法时Promise对象上的一个方法:他其实是放在Promise的原型Peomise.prototype.catch
catch方法 - 多次调用
一个Promise的catch方法是可以被对此调用的:
* 每次调用我们都可以传入一个对应rejecte回调
* 当Promise的状态编程reject的时候,这些回调函数都会被执行
const promise = new Promise((resolve, reject) => {
reject("hahaha")
})
promise.catch(err=>{
console.log("err1":err) //err1 :hahaha
})
promise.catch(res=>{
console.log("err2":err) // err2 :hahaha
})
promise.catch(res=>{
console.log("err3":err) // err3 :hahaha
})
catch方法 - 返回值
catch方法本身是有返回值的,它的返回值是一个Promise,所以我们可以使用then方法或者catch方法进行链式调用
const promise = new Promise((resolve, reject) => {
reject("hahaha")
})
promise.then(res => {
console.log("res result:", res)
}).catch(err=>{
//throw new Error('error message') 抛出错误会调用下一个catch的回调函数
console.log("err1":err) //err1 :hahaha
return "catch return value" //return 一个值 pendding-> fufilled 会调用下一个then的回调函数
}).then(res => {
console.log("res result:", res) // res result:"catch return value"
}).catch(err=>{
console.log("err2":err) // error message
})
finally方法
finally是在ES9(ES2018)中新增的一个特性:表示无论Promise对象无论变成fulfilled还是reject状态,最终都会被执行的代码。
finally方法是不接受参数的,因为无论是fulfilled还是reject状态他都执行
const promise = new Promise((resolve, reject) => {
// resolve("resolve message")
reject("reject message")
})
promise.then(res => {
console.log("res:", res)
}).catch(err => {
console.log("err:", err) //err: reject message
}).finally(() => {
console.log("finally code execute") // finally code execute
})
前面我们学习的then、catch、finally方法都属Promise的实例方法,都是存放在Promise的Prototype上的
下面我们学习一下Promsise的方法
resolve方法
Promise.resolve(value)方法返回一个以给定值解析后的Promise 对象
Promise.resolve()的用法相当于new Promise(),并且执行resolve操作:
Promise.resolve("aky")
//等价于
new Promise((resolve)=>resolve("aky"))
resolve参数的形态与对应的返回值
- 情况一:参数是一个普通的值或者对象 ,返回这个值的
promise对象 - 情况二:参数本身是
Promise,返回这个promise - 情况三:参数是一个
thenable,返回的promise会“跟随”这个thenable的对象,采用它的最终状态
rejecte方法
reject方法类似于resolve方法,只是会将Promise对象的状态设置为reject状态。
Promise.re()的用法相当于new Promise(),并且执行reject操作:
Promise.reject("aky")
//等价于
new Promise((resolve,reject)=>reject("aky"))
Promise.reject传入的参数无论是什么形态,都会直接作为reject状态的参数传递到catch的
all方法
Promise.all的作用是将多个Promise包裹在一起形成一个新的Promise
新的Promise状态由包裹的所有的Promise共同决定
- 当所有的
Promise状态编程fufilled状态时,新的Promise状态为fufilled,并且会将所有Promise的返回值组成一个数组 - 当一个
Promise状态为reject时,新的Promise状态为reject,并返回第一个reject的返回值作为参数
// 创建多个Promise
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(11111)
}, 1000);
})
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(22222)
//reject(22222)
}, 2000);
})
const p3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(33333)
}, 3000);
})
// 需求: 所有的Promise都变成fulfilled时, 再拿到结果
// 意外: 在拿到所有结果之前, 有一个promise变成了rejected, 那么整个promise是rejected
Promise.all([p1, p2, p3, "aaaa"]).then(res => {
console.log(res) //[11111,22222,33333,"aaaa"]
}).catch(err => {
console.log("err:", err) // err :2222
})
allSettled方法
Promise.all方法有一个缺陷:当其中一个Promise编程reject状态时,新的Promise就会立即编程对应的reject状态,那么对于resolve的,依然处于pendding状态的Promise,我们是获取不到结果的。
在ES11中,新添加了新的API Promise.allSettled
- 该方法会在所有的
Promise都有结果(settled),无论是fulfilled,还是rejected时,才会有最终的状态 - 并且这个
Promise的结果一定是fufilled
// 创建多个Promise
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(11111)
}, 1000);
})
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject(22222)
}, 2000);
})
const p3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(33333)
}, 3000);
})
// allSettled
Promise.allSettled([p1, p2, p3]).then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
/**[
{ status: 'fulfilled', value: 11111 },
{ status: 'rejected', reason: 22222 },
{ status: 'fulfilled', value: 33333 }
]
*/
race方法
如果有一个Promise有了结果,我们就希望决定最终新Promise的状态,那么可以使用race方法
// 创建多个Promise
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(11111)
}, 3000);
})
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject(22222)
}, 500);
})
const p3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(33333)
}, 1000);
})
// race: 竞技/竞赛
// 只要有一个Promise变成fulfilled状态, 那么就结束
// 意外:
Promise.race([p1, p2, p3]).then(res => {
console.log("res:", res)
}).catch(err => {
console.log("err:", err) //err :22222
})
any方法
any方法是ES12中新增的方法,和race方法是类似的
any方法会等到一个fulfilled状态,才会决定新Promise的状态- 如果所有的
Promise都是reject的,那么也会等到所有的Promise都变成rejected状态 - 如果所有的
Promise都是rejected的,那么会报一个AggregateError的错误。
手写Promise的部分方法
Pormise类的实现
创建一个promise实例的时候会传入一个executor回调函数,并且执行这个函数,回调函数接收两个固定的函数参数resolve、reject,作用是将pending状态变为fufilled、rejected状态,并将成功数据或者错误报告保存起来
const PROMISE_STATUS_PENDING = "pending"
const PROMISE_STATUS_FUFILLED = "fufilled"
const PROMISE_STATUS_REJECT = "rejected"
class MyPromise {
constructor(executor){
this.status = PROMISE_STATUS_PENDING
this.value = undefined
this.reason = undefined
//定义resolve函数 把成功数据当作参数传入
const resolve = (value)=>{
//promise状态一经改变不在发生变化,所以判断,如果不是pending状体就不会执行
if(this.status === PROMISE_STATUS_PENDING){
this.status = PROMISE_STATUS_FUFILLED //改变状态
this.value = value //保存成功数据
console.log('resolve被调用') //测试用的
}
}
//定义reject函数,并把错位信息作为参数传入
const reject = (reason) => {
//promise状态一经改变不在发生变化,所以判断,如果不是pending状体就不会执行
if(this.status === PROMISE_STATUS_PENDING){
this.status = PROMISE_STATUS_REJECT
this.reason = reason // 保存错误信息
console.log('reject被调用') //测试用的
}
}
executor(resolve,reject) //执行erecutor回调函数
}
}
创建promise的实例
const promise = new MyPromise((resolve,reject)=>{
console.log("pending状态")
resolve(1111)
//reject(2222)
})
打印结果:
promise then方法的实现
promise的then方法也接收两个函数参数,onfufilled和onrejected函数,分别在成功时调用并把数据传入,在失败是调用并把错误信息传入
const PROMISE_STATUS_PENDING = "pending"
const PROMISE_STATUS_FUFILLED = "fufilled"
const PROMISE_STATUS_REJECT = "rejected"
class MyPromise {
constructor(executor){
this.status = PROMISE_STATUS_PENDING
this.value = undefined
this.reason = undefined
//定义resolve函数 把成功数据当作参数传入
const resolve = (value)=>{
//promise状态一经改变不在发生变化,所以判断,如果不是pending状体就不会执行
if(this.status === PROMISE_STATUS_PENDING){
this.status = PROMISE_STATUS_FUFILLED //改变状态
queueMicrotask(() => {
this.value = value
this.onFulfilled(this.value)
});
}
}
//定义reject函数,并把错位信息作为参数传入
const reject = (reason) => {
//promise状态一经改变不在发生变化,所以判断,如果不是pending状体就不会执行
if(this.status === PROMISE_STATUS_PENDING){
this.status = PROMISE_STATUS_REJECT
queueMicrotask(() => {
this.reason = reason
this.onRejected(this.reason)
})
}
}
executor(resolve,reject) //执行erecutor回调函数
}
// then方法的实现
then(onFufilled,onRejected){
this.onFufilled = onFufilled
this.onFejected = onRejected
}
使用queueMicrotask方法包裹的原因:在创建新的promise实例的时候会自行executor回到函数,那么就会去执行resolve或者reject函数,如果没有用queueMicrotask方法包裹,代码顺序执行,此时then方法没有调用执行,此时onFufilled和onRejected还没有传值,所以会报错onFufilled is not function,onRejected is not function;queueMicrotask属于微任务,在下一次事件循环中执行,在主线程执行完成后在执行
then方法实现的优化
优化一: then方法多次执行和确定Promise状态后,再次调用then
上面实现的then方法不能还进行多次调用
const promise = new MyPromise((resolve,reject)=>{
console.log("pending状态")
resolve(1111)
//reject(2222)
})
// 调用then方法多次调用
promise.then(res => {
console.log("res1:", res)
}, err => {
console.log("err:", err)
})
promise.then(res => {
console.log("res2:", res)
}, err => {
console.log("err2:", err)
})
//执行结果为 res2: 1111
多次调用then方法,由于我们对onFufilled和onRejected使用的时赋值操作,所以后面的回调函数会覆盖前面的,我们希望的时多次调用能够多次执行。
我们可以将onFufilled和onRejected回调函数保存到一个数组中,执行resolve或reject的时候遍历执行
class MyPromise {
constructor(executor){
this.status = PROMISE_STATUS_PENDING
this.value = undefined
this.reason = undefined
this.onFufilledFns = [] //存储多次调用then成功的回调
this.onRejectedFns = [] //存储多次调用then失败的回调
//定义resolve函数 把成功数据当作参数传入
const resolve = (value)=>{
//promise状态一经改变不在发生变化,所以判断,如果不是pending状体就不会执行
if(this.status === PROMISE_STATUS_PENDING){
queueMicrotask(() => {
if(this.status! == PROMISE_STATUS_PENDING) return
this.status = PROMISE_STATUS_FUFILLED //改变状态
this.value = value
//this.onFulfilled(this.value)
//遍历成功的回调
this.onFufilledFns.forEavch((onFufilled)=>{
onFufilled(this.value)
})
})
}
}
//定义reject函数,并把错位信息作为参数传入
const reject = (reason) => {
//promise状态一经改变不在发生变化,所以判断,如果不是pending状体就不会执行
if(this.status === PROMISE_STATUS_PENDING){
//添加微任务
queueMicrotask(() => {
if(this.status! == PROMISE_STATUS_PENDING) return
this.status = PROMISE_STATUS_REJECT
this.reason = reason
//this.onRejected(this.reason)
//遍历失败的回调
this.onFufilledFns.forEavch((onRejected)=>{
onRejected(this.value)
})
})
})
}
}
executor(resolve,reject) //执行erecutor回调函数
}
// then方法的实现
then(onFufilled,onRejected){
// 1、如果then调用的时候,状态已经确定下来了
if (this.status === PROMISE_STATUS_FULFILLED && onFulfilled) {
onFulfilled(this.value)
}
if (this.status === PROMISE_STATUS_REJECTED && onRejected) {
onRejected(this.reason)
}
// 2.将成功回调和失败的回调放到数组中
if (this.status === PROMISE_STATUS_PENDING) {
//this.onFufilled = onFufilled
this.onFulfilledFns.push(onFulfilled) //将成功回调放到数组中
//this.onFejected = onRejected
this.onRejectedFns.push(onRejected) //将失败的回调放到数组中
}
}
}
const promise = new HYPromise((resolve, reject) => {
console.log("状态pending")
resolve(1111) // resolved/fulfilled
reject(2222)
})
// 调用then方法多次调用
promise.then(res => {
console.log("res1:", res)
}, err => {
console.log("err:", err)
})
promise.then(res => {
console.log("res2:", res)
}, err => {
console.log("err2:", err)
})
//在确定Promise状态之后, 再次调用then
setTimeout(() => {
promise.then(res => {
console.log("res3:", res)
}, err => {
console.log("err3:", err)
})
}, 1000)
优化二: then方法的链式调用
then方法能链式调用的原因:then方法返回值仍然是Promise对象,上面代码中的then需要返回一个promise
// 工具函数
function execFunctionWithCatchError(execFn, value, resolve, reject) {
try {
const result = execFn(value)
resolve(result)
} catch(err) {
reject(err)
}
}
class MyPromise {
.... // 上面代码
then(onFufilled,onRejected){
return new MyPromise((resolve,reject)=>{
// 1、如果then调用的时候,状态已经确定下来了
if (this.status === PROMISE_STATUS_FULFILLED && onFulfilled) {
//const newValue =onFulfilled(this.value) //拿到执行成功回调的返回值
//resolve(newValue)
//try {
// const newValue = onFulfilled(this.value)
// resolve(newValue)
// } catch(err) {
// reject(err)
//}
execFunctionWithCatchError(onFulfilled, this.value, resolve, reject)
}
if (this.status === PROMISE_STATUS_REJECTED && onRejected) {
//cosnt newReason = onRejected(this.reason) //拿到执行失败回调的返回值
//resolve(newReason)
// try {
// cosnt newReason = onRejected(this.reason)
// resolve(newReason)
// } catch(err) {
// reject(err)
// }
execFunctionWithCatchError(onRejected, this.reason, resolve, reject)
}
// 2.将成功回调和失败的回调放到数组中
if (this.status === PROMISE_STATUS_PENDING) {
//this.onFufilled = onFufilled
this.onFulfilledFns.push(()=>{
//const newValue = onFulfilled(this.value)
//resolve(newValue)
//try {
// const newValue = onFulfilled(this.value)
// resolve(newValue)
// } catch(err) {
// reject(err)
// }
execFunctionWithCatchError(onFulfilled, this.value, resolve, reject)
}) //将成功回调放到数组中
//this.onFejected = onRejected
this.onRejectedFns.push(()=>{
//const newReason = onRejected(this.reason)
//resolve(newReason)
//try {
// cosnt newReason = onRejected(this.reason)
// resolve(newReason)
// } catch(err) {
// reject(err)
// }
execFunctionWithCatchError(onRejected, this.reason, resolve, reject)
}) //将失败的回调放到数组中
}
})
}
const promise = new MyPromise((resolve, reject) => {
console.log("状态pending")
// resolve(1111) // resolved/fulfilled
reject(2222)
// throw new Error("executor error message")
})
// 调用then方法多次调用
promise.then(res => {
console.log("res1:", res)
return "aaaa"
// throw new Error("err message")
}, err => {
console.log("err1:", err)
return "bbbbb"
// throw new Error("err message")
}).then(res => {
console.log("res2:", res)
}, err => {
console.log("err2:", err)
})
//结果:状态pending err1:2222 res2:bbbb
catch方法实现
catch方法会在promise状态为rejected时候调用并传入错误信息,其实本质上为then方法分别传入undefined和onRejected参数
class MyPromise {
....// 省略
then(onFufilled,onRejected){
//将上一次为执行的失败的回调抛出
const defalutOnRejected = err =>{throw err}
onRejected = onRejected || defalutOnRejected
return new MyPromise((resolve,reject)=>{
// 1、then调用的时候promise状态已经为fufilled
if(this.status === PROMISE_STATUS_FUFILLED && onfufilled){
try{
cosnt newValue = onfufilled(this.value)
resolve(newValue)
}catch(err){
reject(err)
}
}
if(this.status === PROMISE_STATUS_REJECT && onREJECTED){
try{
cosnt newReason = onRejected(this.value)
resolve(newReason)
}catch(err){
reject(err)
}
}
// 2 、 将成功的回调放入回回调数组中
if(this.status === PROMISE_STATUS_PENDING){
if(onFufilled) this.onfufilled.push(()=>{
try{
cosnt newValue = onFufilled(this.value)
resolve(newValue)
}catch(err){
reject(err)
})
if(onRejected) this.onrejected.push(()=>{
try{
cosnt newReason = onRejected(this.value)
resolve(newReason)
}catch(err){
reject(err)
}
})
}
})
}
catch(undefined,onReject){
this.then(undefined,onReject)
}
finally方法实现
finally方法本质就是调用then方法,并且传入回到函数
calss MyPromise {
....
finally (onFinally){
this.then(()=>{
onFinally()
},()=>{
onFinally()
})
all和allSettled方法实现
all方法的实现关键是什么时候执行resolve,什么时候执行reject
class MyPromise {
static all(promisesArr){
return new MyPromise((resolve,reject)=>{
const values = []
promisesArr.forEach(promise=>{
promise.then(res=>{
value.push(res)
if(values.length ===promisesArr.length){
resolve(values)
},err=>{
reject(err)
})
})
})
}
static allSettled(promisesArr)[
return new MyPromise((resolve,reject)=>{
const results = []
promise.forEach((promise)=>{
promise.then(res=>{
results.push({status:PROMISE_STATUS_FUFILLED,value:res})
if(results.length ===promise.length){
resolve(results)
}
},err=>{
results.push({status:PROMISE_STATUS_REJECT,value:err})
if (results.length === promises.length) {
resolve(results)
}
})
})
})
}
race方法实现
class Mypromise {
...
static race(promises) {
return new HYPromise((resolve, reject) => {
promises.forEach(promise => {
// promise.then(res => {
// resolve(res)
// }, err => {
// reject(err)
// })
promise.then(resolve, reject)
})
})
}
总结
MyPromise各个方法实现的总代码如下
//工具函数
function execFunctionWithCatchError(execFn,value,resolve,reject){
try{
const result = execFn(value)
resolve(reslut)
}catch(err){
reject(err)
}
}
class Mypromise{
const PROMISE_STATUS_PENDING = 'pending'
const PROMISE_STATUS_FULFILLED = 'fulfilled'
const PROMISE_STATUS_REJECTED = 'rejected'
constructor(executor){
this.status = PROMISE_STATUS_PENDING
this.value = undefined
this.reson = undefined
this.onFufilledFns = []
this.onRejectedFns = []
//resolve函数
const resolve = (value)=> {
if(this.status === PROMISE_STATUS_PENDING ){
//微任务
queueMicrotask(() => {
this.status = PROMISE_STATUS_FULFILLED
this.value = value
this.onFufilledFns.forEach((fn)=>{
fn(this.value)
})
}
}
//reject函数
const reject = (reason) => {
if(this.status === PROMISE_STATUS_PENDING){
//微任务
queueMicrotask(()=>{
this.status = PROMISE_STATUS_REJECTED
this.reason = reason
this.onRejectedFns.forEach(fn=>{
fn(this.reason)
})
})
}
executor(resolve,reject)
}
//then方法
then(onFufilled,onRejected){
const defaultOnRejected = (err) =>{ throw err}
onRejected = onRejected || defaultOnRejected
return new MyPromise((resolve,reject)=>{
// then方法执行的时候,promise状态已经是fufilled
if(this.status === PROMISE_STATUS_FULFILLED && onFufilled){
execFunctionWithCatchError(onFufilled,this,value,resolve,reject)
}
if(this.status ===PROMISE_STATUS_REJECTED && onRejected){
execFunctionWithCatchError(onFufilled,this,value,resolve,reject)
}
//then方法仍是pending状态下,将成功或者失败回调添加数组中
if(this.status === PROMISE_STATUS_PENDING){
if(onFufilled) this.onFufilledFns.push(()=>{
execFunctionWithCatchError(onFufilled,this,value,resolve,reject)
})
if (onRejected) this.onRejectedFns.push(() => {
execFunctionWithCatchError(onRejected, this.reason, resolve, reject)
})
}
})
}
//catch方法
catch(onRejected){
return this.then(undefined,onRejected)
}
//finally方法
finally(onfinally){
this.then(res=>{
onfinally()
},err=>{
onfinally()
})
}
//all方法
static all(promsiesArr){
const values = []
return new MyPrmoise((resolve,reject)=>{
promsiesArr.forEach(promise=>{
promsie.then(res=>{
values.push(res)
if(values.length === promisesArr.length){
resolve(values)
}
},err=>{
reject(err)
})
})
})
//allSettled方法
static allSettled(promsiesArr){
return new MyPromise((resolve,reject)=>{
const results = []
promisesArr.forEach(promise=>{
promsie.then(res=>{
resluts.push({status:PROMISE_STATUS_FULFILLED,value:res})
if(result.length === promisesArr.length){
resolve(values)
}
},err=>{
results.push({status:PROMISE_STATUS_REJECTED,value:err})
if(results.length === promisesArr.length){
resolve(values)
}
})
})
})
}
//race方法
static race(promises) {
return new HYPromise((resolve, reject) => {
promises.forEach(promise => {
// promise.then(res => {
// resolve(res)
// }, err => {
// reject(err)
// })
promise.then(resolve, reject)
})
})
}
}