普及一下: promise没有源码,它的底层的浏览器v8已经实现好的。实际是通过c++实现的
一、脑海里构建出 promise该有的结构
class myPromise {
constructor () {
this.status = 'pending'
}
then () {}
catch () {}
finally () {}
all () {}
/**
* allSettled 不常用
* 等到所有promises都已敲定(settled)(每个promise都已兑现(fulfilled)或已拒绝(rejected))。
返回一个promise,该promise在所有promise完成后完成。并带有一个对象数组,每个对象对应每个promise的结果。
*/
allSettled () { }
any () {}
race () {}
reject () {}
resolve () {}
}
基本结构已经出来了, 我们先new 一个promise看看是个啥子
const p = new Promise((resolve, reject) => {
})
console.log(p)
是个pending状态的Promise,只有当我们resolve的时候才会变成fulfilled状态,当我们调用reject的时候变成rejected状态
- 根据它的打印结果先定义好构造函数
constructor (handle) {
this['[[PromiseState]]'] = 'pending'
this['[[PromiseResult]]'] = undefined
}
三、解析实现
1、 由上可以看到 new 一个promis实例,给promise传入了一个函数(handle),所以我们要在promise中接收这个函数(handle),该函数里面又包含了一个resolve函数调用,一个reject函数调用,因此handle还有两个函数参数
2、根据上面打印出来的结果可以知道 当我们在外部resolve或者reject的时候,要改变promiseState,以及要把结果集放入PromiseResult中
class myPromise {
constructor (handle) {
this['[[PromiseState]]'] = 'pending'
this['[[PromiseResult]]'] = undefined
handle((res) => {
this['[[PromiseState]]'] = 'fulfilled'
this['[[PromiseResult]]'] = res
}, (err) => {
this['[[PromiseState]]'] = 'rejected'
this['[[PromiseResult]]'] = err
}) // 传递过来立即执行
}
then () {}
catch () {}
finally () {}
all () {}
/**
* allSettled 不常用
* 等到所有promises都已敲定(settled)(每个promise都已兑现(fulfilled)或已拒绝(rejected))。
返回一个promise,该promise在所有promise完成后完成。并带有一个对象数组,每个对象对应每个promise的结果。
*/
allSettled () { }
any () {}
race () {}
reject () {}
resolve () {}
}
const myP = new myPromise((resolve, reject) => {
})
console.log('myP', myP)
then
3、接下来我们去康康then. then原来接收两个回调函数!但是在日常开发中都习惯了把错误信息reject到catch中
then (successCallback, failCallback) {
if (this['[[PromiseState]]'] === 'fulfilled') {
successCallback && successCallback(this['[[PromiseResult]]'])
} else {
failCallback && failCallback(this['[[PromiseResult]]'])
}
}
----我这样纸写then是可以执行resolve ,reject的但是我加上setTimeout就啥也不是了。 这样子写then其实是个立即执行函数。所以还得改造一下
4、不能给他立即执行, 所以可以先把回调函数存储起来,然后在resolve,或者reject的时候再去执行回调
---注:只有在调取了resolve或者reject之后才执行回调函数---
class myPromise {
constructor (handle) {
this['[[PromiseState]]'] = 'pending'
this['[[PromiseResult]]'] = undefined
this.resolveFn = undefined
this.rejectFn = undefined
handle(this.#resolve.bind(this), this.#reject.bind(this)) //
}
/**
* 为了方便维护,我把resolve与reject作为内部函数
*/
#resolve (val) {
this['[[PromiseState]]'] = 'fulfilled'
this['[[PromiseResult]]'] = val
console.log('this.resolveFn', this.resolveFn)
this.resolveFn(val)
}
#reject (err) {
this['[[PromiseState]]'] = 'rejected'
this['[[PromiseResult]]'] = err
this.rejectFn(err)
}
then (successCallback, failCallback) {
this.resolveFn = successCallback
this.rejectFn = failCallback
}
}
const myP = new myPromise((resolve, reject) => {
setTimeout(() => {
resolve('jdjkkjdd')
}, 1000)
})
myP.then(res => {
console.log('res', res)
})
console.log('myP', myP)
5、接下来聊一聊多个then,不是链式的多个then
const p = new Promise((resolve, reject) => {
resolve('resulr')
})
p.then(res => {
setTimeout(() => {
console.log('111', res)
}, 1000)
}, err => {
console.log(err)
})
p.then(res => {
console.log('2222',res)
})
console.log(p)
// ...
//是类似这种的多个then
---结果是不是还是很正常的 因为我111加了setTimeout
但是我们写的promise只会执行最后一次的,为啥呢??
因为我们定义的this['[[PromiseResult]]']会被覆盖掉。所以我们要把resolveFn、rejectFn变成数组的形式 把回调函数都保存起来
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)
}
}
run()
}
#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)
}
}
run()
}
then (successCallback, failCallback) {
this.resolveFn.push(successCallback)
this.rejectFn.push(failCallback)
}
}
const myP = new myPromise((resolve, reject) => {
setTimeout(() => {
resolve('jdjkkjdd')
}, 1000)
})
myP.then(res => {
console.log('res', res)
})
myP.then(res => {
console.log('2222', res)
})
console.log('myP', myP)
我不行了 休息一会儿。promise太难搞了,,,,好看记得一键三连哦~ 后期会继续更新完成