上次分析到了多个then调用
还没有看上一篇文章的小伙伴可以先看上半部分,手写一个promise终结(一) - 掘金 (juejin.cn)
其实上次我是发现了我一直用setTimeout执行回调,结果把setTimeout去掉之后就啥也不是了。
then (successCallback, failCallback) {
if (this['[[PromiseState]]'] === 'fulfilled') {
successCallback && successCallback(this['[[PromiseResult]]'])
} else if (this['[[PromiseState]]'] === 'rejected') {
failCallback && failCallback(this['[[PromiseResult]]'])
} else if (this['[[PromiseState]]'] === 'pending') {
this.resolveFn.push(successCallback)
this.rejectFn.push(failCallback)
}
}
}
const myP = new myPromise((resolve, reject) => {
reject('err')
})
myP.then(res => {
console.log('res', res)
}, err => {
console.log('err', err)
})
我把then改造了一下, 就是根据它的状态去判断是否要立即执行还是存储。
其实还有一个办法就是把#resolve和#reject中的run()setTimeout一下
setTimeout( () => { run() })这样也可
┭┮﹏┭┮ 太难搞了, 我写那么多if判断搞啥子。日常开发中太多的if else 估计会被喷死的
// 222 --- 333- 555 -- 444 --- 111 预期结果
setTimeout (() => {
console.log('1111')
}, 2000)
console.log('222')
const myP = new myPromise((resolve, reject) => {
console.log('333')
resolve('suss')
})
myP.then(res => {
console.log('444')
console.log('res', res)
}, err => {
console.log('err', err)
})
console.log('5555')
console.log('myP', myP)
结果却是这样的~, 为啥子呀,裂开。
由上可知,我的promise没有所谓的微、宏任务就是个同步的
因为我的promise resolve与then之间没有设置微、宏任务嘛
所以还是得 setTimeout( () => { run() }),但是更确切的应该是微任务的写法
const observer = new MutationObserver(run)
observer.observe(document.body, {
attributes: true
})
document.body.setAttribute('what', 'shenmewanyier')
这个小插曲结束了, 下面继续
6、链式调用。一般情况下链式调用的关键是 return this 但是如果这里返回一个return this 的话就会出现每次链式之间好像都没有什么关联, 永远返回的是new 出来的实例, 所以要每次都返回一个新的promise
then (successCallback, failCallback) {
return new myPromise ((resolve, reject) => {
let resolveFn = (res) => {
let val = successCallback && successCallback(res) // 拿到回调函数的执行结果
resolve(val)
}
this.resolveFn.push(resolveFn)
let rejectFn = (res) => {
let val = failCallback && failCallback(res)
reject(val)
}
this.rejectFn.push(rejectFn)
})
}
const myP = new myPromise((resolve, reject) => {
resolve('suss')
})
myP.then(res => {
console.log('res', res)
return 'fhfh'
}).then(res => {
console.log('122', res)
})
现在我们只能处理return一个普通值的情况,promise其实还可以return 一个promise, 咋整。 那就是去取promise。then返回的值就差不多了
then (successCallback, failCallback) {
return new myPromise ((resolve, reject) => {
let resolveFn = (res) => {
let val = successCallback && successCallback(res) // 拿到回调函数的执行结果
// 判断val的类型
if (val instanceof myPromise) {
// val.then(a => {
// resolve(a)
// })
val.then(resolve)
} else {
resolve(val)
}
}
this.resolveFn.push(resolveFn)
let rejectFn = (res) => {
let val = failCallback && failCallback(res)
reject(val)
}
this.rejectFn.push(rejectFn)
})
}
then 终于结束了,这东西太难搞了。加油继续奋起
后面有了解到catch、finally为原型方法, race、 all、allSettled、 resolve、 reject称为静态方法
catch
接下来我们讲讲catch, 其实catch我们上面在then中已经实现了, 所以我们在catch方法中重新调用一下then就可以了
catch (fn) {
return this.then(undefined, fn)
}
resolve
我们先打印看看resolve之后会返回什么
const p = Promise.resolve('success')
console.log(p)
其实也是一个promise对象, 所以我们直接return一个promise给他就好
注意:resolve是一个静态方法
static resolve (val) {
return new myPromise (resolve => {
resolve(val)
})
}
reject
reject跟resolve是一样的道理,直接上代码!
static reject (err) {
return new myPromise ((resolve, reject) => {
reject(err)
})
}
race
race就是一个数组,只拿取最快得到的执行结果,就终止了
static race (list) {
return new myPromise((resolve, reject) => {
list.forEach(element => {
item.then(res => { // 谁最快,谁先调取
resolve(res)
}, err => {
reject(err)
})
});
})
}
allSettled
allSettled与all的区别就是allSettled 不管成功还是失败都会去收集,而all只收集成功的结果
先来看一下allSettled 原有的样子吧
const p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('111')
}, 1000)
})
const p2 = new Promise((resolve, reject) => {
reject('222')
})
const p3 = new Promise((resolve, reject) => {
resolve('333')
})
Promise.allSettled([p, p2, p3]).then(res => {
console.log('allSettled', res)
}, err => {
console.log('allSettled err', err)
})
console.log(p)
所以该有的样子是一个数组,里面每个对象对应相应结果集,包含status,成功:value, 失败: reason。下面开始吧
static allSettled (lists) {
let resArr = new Array(lists.length) // lists的结果集要一一对应且长度相等
let num = 0 // lists是否执行完毕
return new myPromise( resolve => {
lists.forEach((item, key) => {
let obj = {}
item.then(res => {
obj['status'] = 'fulfilled'
obj['value'] = res
resArr[key] = obj
num++
if (num >= lists.length) {
resolve(resArr)
}
}, err => {
obj['status'] = 'rejected'
obj['reason'] = err
resArr[key] = obj
num++
if (num >= lists.length) {
resolve(resArr)
}
})
})
})
}
const myP = new myPromise((resolve, reject) => {
setTimeout(() => {
resolve('111')
}, 1000)
})
const myP2 = new myPromise((resolve, reject) => {
reject('222')
})
const myP3 = new myPromise((resolve, reject) => {
resolve('332')
})
myPromise.allSettled([myP, myP2, myP3]).then(res => {
console.log('结果', res)
})
allSettled 已经搞定了, 还差最后两个, finally、all, 渣油
all
all 就是碰到reject就停止收集,并且只返回错误结果, 如果都是成功就返回成功的list, 还是看看原有的样子吧
const p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('111')
}, 1000)
})
const p2 = new Promise((resolve, reject) => {
resolve('222')
})
const p3 = new Promise((resolve, reject) => {
resolve('333')
})
Promise.all([p, p2, p3]).then(res => {
console.log('allSettled', res)
}, err => {
console.log('err', err)
})
动手吧!!
static all (list) {
let successArr = new Array(list.length) // 成功的结果集
let flag = false // 是否有错误信息
const length = list.length
return new myPromise((resolve, reject) => {
for (let i = 0; i < length; i++ ) {
list[i].then(res => {
successArr[i] = res
if (i >= list.length -1 && !flag) {
resolve(successArr)
}
}, err => {
flag = true
reject(err)
return
})
}
})
}
finally
finally就是不管是resolve,还是reject都会去执行,且没有参数返回值。那不是搜搜搞定!!!
finally (Callback) {
if (this['[[PromiseState]]'] !== 'pending') {
Callback && Callback()
}
}
终于结束了!最后附上完整代码
class myPromise {
constructor (handle) {
this['[[PromiseState]]'] = 'pending'
this['[[PromiseResult]]'] = undefined
this.resolveFn = []
this.rejectFn = []
handle(this.#resolve.bind(this), this.#reject.bind(this)) //
}
/**
* 为了方便维护,我把resolve与reject作为内部函数
*/
#resolve (val) {
this['[[PromiseState]]'] = 'fulfilled'
this['[[PromiseResult]]'] = val
// this.resolveFn && this.resolveFn(val)
// 从尾推入, 从头拿出
const run = () => {
let cb
while (cb = this.resolveFn.shift()) {
cb && cb(val)
}
}
const observer = new MutationObserver(run)
observer.observe(document.body, {
attributes: true
})
document.body.setAttribute('what', 'shenmewanyier')
}
#reject (err) {
this['[[PromiseState]]'] = 'rejected'
this['[[PromiseResult]]'] = err
// this.rejectFn && this.rejectFn(err)
// 从尾推入, 从头拿出
const run = () => {
let cb
while (cb = this.rejectFn.shift()) {
cb && cb(err)
}
}
const observer = new MutationObserver(run)
observer.observe(document.body, {
attributes: true
})
document.body.setAttribute('what', 'shenmewanyier')
}
then (successCallback, failCallback) {
return new myPromise ((resolve, reject) => {
let resolveFn = (res) => {
let val = successCallback && successCallback(res) // 拿到回调函数的执行结果
// 判断val的类型
if (val instanceof myPromise) {
// val.then(a => {
// resolve(a)
// })
val.then(resolve)
} else {
resolve(val)
}
}
this.resolveFn.push(resolveFn)
let rejectFn = (res) => {
let val = failCallback && failCallback(res)
reject(val)
}
this.rejectFn.push(rejectFn)
})
}
catch (fn) {
return this.then(undefined, fn)
}
finally (Callback) {
if (this['[[PromiseState]]'] !== 'pending') {
Callback && Callback()
}
}
static all (list) {
let successArr = new Array(list.length) // 成功的结果集
let flag = false // 是否有错误信息
const length = list.length
return new myPromise((resolve, reject) => {
for (let i = 0; i < length; i++ ) {
list[i].then(res => {
successArr[i] = res
if (i >= list.length -1 && !flag) {
resolve(successArr)
}
}, err => {
flag = true
reject(err)
return
})
}
})
}
/**
* allSettled 不常用
* 等到所有promises都已敲定(settled)(每个promise都已兑现(fulfilled)或已拒绝(rejected))。
返回一个promise,该promise在所有promise完成后完成。并带有一个对象数组,每个对象对应每个promise的结果。
*/
static allSettled (lists) {
let resArr = new Array(lists.length) // lists的结果集要一一对应且长度相等
let num = 0 // lists是否执行完毕
return new myPromise(resolve => {
lists.forEach((item, key) => {
let obj = {}
item.then(res => {
obj['status'] = 'fulfilled'
obj['value'] = res
resArr[key] = obj
num++
if (num >= lists.length) {
resolve(resArr)
}
}, err => {
obj['status'] = 'rejected'
obj['reason'] = err
resArr[key] = obj
num++
if (num >= lists.length) {
resolve(resArr)
}
})
})
})
}
static race (list) {
return new myPromise((resolve, reject) => {
list.forEach(element => {
element.then(res => { // 谁最快,谁先调取
resolve(res)
}, err => {
reject(err)
})
});
})
}
static reject (err) {
return new myPromise ((resolve, reject) => {
reject(err)
})
}
static resolve (val) {
return new myPromise (resolve => {
resolve(val)
})
}
}
const myP = new myPromise((resolve, reject) => {
setTimeout(() => {
resolve('111')
}, 3000)
})
myP.finally(() => {
console.log('结束')
})
const myP2 = new myPromise((resolve, reject) => {
resolve('222')
})
const myP3 = new myPromise((resolve, reject) => {
resolve('332')
})