前言:昨日分享到then方法,今日继续分享剩余的方法。在理解此文章之前,务必把(一)消化哦!
一、catch:
catch(onRejected) {
return this.then(undefined, onRejected)
}
----------------以下为catch方法测试代码------------
p1.then(res => {
console.log("res:", res)
}).catch(err => {
console.log("err:", err)
})
这样写会出现问题:假如P1没有传err,则onRejected函数就为空了;正确的思路是假如没有传,则默认throw err===》基于此,设置onRejected的默认值来解决这个问题。 因此,修改then代码如下:
then(onFulfilled, onRejected) {
const defaultOnRejected = (err => { throw err })
onRejected = onRejected || defaultOnRejected
//--------------------以上是新增的代码-------------------------------
return new selfPromise((resolve, reject) => {
//同之前代码相同
}
}
二、finally:
finally(onFinally) {
return this.then(() => {
onFinally()
}, () => {
onFinally()
})
}
// ----------------以下为finally方法测试代码------------
p1.then(res => {
console.log("res1:", res)
return "aaaaa"
}).then(res => {
console.log("res2:", res)
}).catch(err => {
console.log("err:", err)
}).finally(() => {
console.log("finally")
})
问题:调完then==>调catch===>调finally。注意:因为catch(undefined,onRejected),这个undefined隔绝了then的onFulfilled函数向finally的传递,出现了断层。 对策:设置onFulfilled的默认值。
then(onFulfilled, onRejected) {
const defaultOnFulfilled = value => { return value }
onFulfilled = onFulfilled || defaultOnFulfilled
return new selfPromise((resolve, reject) => {
//同之前代码相同
}
}
四、类方法
4.1 resolve 和reject
在 static resolve(value) 方法中,只需要将 Promise 的状态设置为已完成(fulfilled)并传递对应的 value 值即可。因此,只需要调用 resolve(value) 即可。
而在 static reject(reason) 方法中,需要将 Promise 的状态设置为已拒绝(rejected)并传递拒绝的原因(reason),因此既需要resolve,也需要传reject。
static resolve(value) {
return new selfPromise((resolve) => {
resolve(value)
})
}
static reject(reason) {
return new selfPromise((resolve, reject) => {
reject(reason)
})
}
4.2 all : 可以理解为需要“全部”满足条件才会成功。
static all(promises) {
return new selfPromise((resolve, reject) => {
const values = []
promises.forEach((promise) => {
promise.then(res => {
values.push(res)
if(values.length === promises.length) {
resolve(values)
}
}, err => {
reject(err)
})
})
})
}
4.3 any:可以理解为只需要“任意一个”满足条件就会成功(与all相反)
static any(promises) {
const reasons = []
return new selfPromise((resolve, reject) => {
promises.forEach(promise => {
promise.then(res => {
resolve(res)
}, err => {
reasons.push(err)
if(reasons.length === promises.length) {
reject(new AggregateError(reasons))
}
})
})
})
}
补充:AggregateError是在 ECMAScript 2021 (ES12) 中引入的内置错误类型,较低版本的node不支持,可以通过errors属性在浏览器查看;AggregateError对象包含一个 errors 属性,该属性是一个数组,存储了多个错误对象。
4.4 allSettled:等待所有的 Promise 实例都被解决(settled),不论是成功还是失败。所以Promise.allSettled 的结果永远是已解决的(resolved)。
static allSettled(promises) {
return new selfPromise(resolve =>{
const results = []
promises.forEach((promise) => {
promise.then(res => {
results.push({status: FULFILLED, value: res})
if(results.length === promises.length) {
resolve(results)
}
}, err => {
results.push({status: REJECTED, value: err})
if(results.length === promises.length) {
resolve(results)
}
})
})
})
}
注意:返回结果是一个数组对象,每个结果对象包含以下两个属性:
status:"fulfilled"(已完成)或"rejected"(已拒绝)。value或reason:表示对应 Promise 实例的值(如果状态为"fulfilled")或拒绝原因(如果状态为"rejected")。
4.5 race :类似于多个参与者之间的竞赛,谁先跑完,就先返回结果,不论成败。
static race(promises) {
return new selfPromise(((resolve, reject) => {
promises.forEach(promise => {
promise.then(resolve, reject)
})
}))
}
五、手写全部promise代码及测试代码(可copy后自己在编辑器测试帮助自己理解)
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'reject'
class selfPromise {
constructor(executor) {
this.status = PENDING
this.value = undefined
this.reason = undefined
this.onFulfilledFns = []
this.onRejectedFns = []
const resolve = (value) => {
if (this.status === PENDING) {
queueMicrotask(() => {
if (this.status !== PENDING) return
this.value = value
this.status = FULFILLED
this.onFulfilledFns.forEach((fn) => {
fn(this.value)
})
})
}
}
const reject = (reason) => {
if (this.status === PENDING) {
queueMicrotask(() => {
if (this.status !== PENDING) return
this.reason = reason
this.status = REJECTED
this.onRejectedFns.forEach(fn => {
fn(this.reason)
})
})
}
}
try {
executor(resolve, reject)
} catch (error) {
reject(error)
}
}
then(onFulfilled, onRejected) {
const defaultOnRejected = (err => { throw err })
onRejected = onRejected || defaultOnRejected
const defaultOnFulfilled = value => { return value }
onFulfilled = onFulfilled || defaultOnFulfilled
return new selfPromise((resolve, reject) => {
if (this.status === PENDING) {
if (onFulfilled) {
this.onFulfilledFns.push(() => {
try {
const value = onFulfilled(this.value)
resolve(value)
} catch (error) {
reject(error)
}
})
}
if (onRejected) {
this.onRejectedFns.push(() => {
try {
const reason = onRejected(this.reason)
resolve(reason)
} catch (error) {
reject(error)
}
})
}
}
if (this.status === FULFILLED && onFulfilled) {
// onFulfilled(this.value)
try {
const value = onFulfilled(this.value)
resolve(value)
} catch (error) {
reject(error)
}
}
if (this.status === REJECTED && onRejected) {
// onRejected(this.reason)
try {
const reason = onRejected(this.reason)
resolve(reason)
} catch (error) {
reject(error)
}
}
})
}
catch(onRejected) {
return this.then(undefined, onRejected)
}
finally(onFinally) {
return this.then(() => {
onFinally()
}, () => {
onFinally()
})
}
static resolve(value) {
return new selfPromise((resolve) => {
resolve(value)
})
}
static reject(reason) {
return new selfPromise((resolve, reject) => {
reject(reason)
})
}
static all(promises) {
return new selfPromise((resolve, reject) => {
const values = []
promises.forEach((promise) => {
promise.then(res => {
values.push(res)
if(values.length === promises.length) {
resolve(values)
}
}, err => {
reject(err)
})
})
})
}
static allSettled(promises) {
return new selfPromise(resolve =>{
const results = []
promises.forEach((promise) => {
promise.then(res => {
results.push({status: FULFILLED, value: res})
if(results.length === promises.length) {
resolve(results)
}
}, err => {
results.push({status: REJECTED, value: err})
if(results.length === promises.length) {
resolve(results)
}
})
})
})
}
static race(promises) {
return new selfPromise(((resolve, reject) => {
promises.forEach(promise => {
promise.then(resolve, reject)
})
}))
}
static any(promises) {
const reasons = []
return new selfPromise((resolve, reject) => {
promises.forEach(promise => {
promise.then(res => {
resolve(res)
}, err => {
reasons.push(err)
if(reasons.length === promises.length) {
reject(new AggregateError(reasons))
}
})
})
})
}
}
//——————————————————测试代码————————————————————————————————
const p1 = new selfPromise((resolve, reject) => {
// resolve(111111)
reject(222222)
})
//-------以下为then方法的多次调用测试代码
// p1.then(res => {
// console.log("res", res)
// }, err => {
// console.log("err", err)
// })
// p1.then(res2 => {
// console.log("res2", res2)
// }, err2 => {
// console.log("err2", err2)
// })
// ----------以下为then方法的链式调用测试代码---------
// p1.then(res => {
// console.log("res", res)
// }, err => {
// console.log("err", err)
// return "aaa"
// }).then(res2 => {
// console.log("res2", res2)
// }, err2 => {
// console.log("err2", err2)
// })
// ----------------以下为catch方法测试代码------------
// p1.then(res => {
// console.log("res:", res)
// }).catch(err => {
// console.log("err:", err)
// })
// ----------------以下为finally方法测试代码------------
// p1.then(res => {
// console.log("res1:", res)
// return "aaaaa"
// }).then(res => {
// console.log("res2:", res)
// }).catch(err => {
// console.log("err:", err)
// }).finally(() => {
// console.log("finally")
// })
//-------------------以下是类方法:resolve、rejected的测试代码
// selfPromise.resolve("我是value").then(res => {
// console.log("res", res)
// })
// selfPromise.reject("我是reason").catch(err => {
// console.log("Error", err)
// })
//-------------------以下是类方法:all的测试代码
const promise1 = new Promise((resolve,reject) => {
setTimeout(() => { reject(1111) }, 5000)
})
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => { reject(2222) }, 2000)
})
const promise3 = new Promise((resolve, reject) => {
setTimeout(() => { reject(3333) }, 3000)
})
// selfPromise.all([promise1, promise2, promise3]).then(res => {
// console.log("all",res)
// }).catch(err => {
// console.log("err", err)
// // })
// //-------------------以下是类方法:allSettled的测试代码
// selfPromise.allSettled([promise1, promise2, promise3]).then(res => {
// console.log("allSettled",res)
// }).catch(err => {
// console.log("err", err)
// })
// //-------------------以下是类方法:race的测试代码
// selfPromise.race([promise1, promise2, promise3]).then(res => {
// console.log("race",res)
// }).catch(err => {
// console.log("err", err)
// })
// //-------------------以下是类方法:any的测试代码
selfPromise.any([promise1, promise2, promise3]).then(res => {
console.log("any",res)
}).catch(err => {
console.log("errs", err.errors)
})