持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第14天,点击查看活动详情
题外话
这个疫情啊,真滴是服气了,居家快一个月了,居家不是办公就是做饭,脑子都快麻木了,为了活跃自己的大脑,也为了帮助大家增长知识,我给大家分享一点冷知识,嘿嘿嘿……
冷知识:海水中含有大量盐类和多种元素,其中许多元素是人体所需要的。但海水中各种物质浓度太高,远远超过饮用水卫生标准,如果大量饮用,会导致某些元素过量进入人体,影响人体正常的生理功能,严重的还会引起中毒。
所以去海边一定不要尝试喝海水啊~~~~~~~~~
前情回顾
上一篇我们说到then接收两个回调函数,这里我将上一篇的代码展示如下,我们可以验证一下代码的正确性
new MyPromise((resolve, reject) => {
resolve('成功')
}).then(resp => {
console.log(resp);
}, err => {
console.log(err);
})
//成功
正题
Promise.prototype.then()异步处理
我们上面验证了同步代码是可以回调并且接收的,接下来我们看看promise中的异步代码如何接收 需要在promise对象拿到返回值之后再接收返回值
- 我们首先定义一个参数用来存储临时存储成功或者失败的回调函数
- 等待异步代码执行resolve或者reject之后再执行存储的回调函数接收返回值
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise {
constructor(executor) {
executor(this.resolve, this.reject)
}
status = PENDING
resp = undefined
error = undefined
//1.1 定义变量用来临时存储成功或者失败的回调函数
successCallback = undefined
failCallback = undefined
resolve = (resp) => {
if (this.staus !== PENDING) return
this.status = FULFILLED
this.resp = resp
//2 判断代码是否是成功回调的,如果是九江回调的返回值一并返回
this.successCallback && this.successCallback(this.resp)
}
reject = (error) => {
if (this.staus !== PENDING) return
this.status = REJECTED
this.error = error
//同理
this.failCallback && this.failCallback(this.error)
}
then(successCallback, failCallback) {
if (this.status === FULFILLED) {
successCallback(this.resp)
} else if (this.status === REJECTED) {
failCallback(this.error)
} else {
//1.2 将回调函数临时存储起来
this.successCallback = successCallback
this.failCallback = failCallback
}
}
}
验证
new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve('成功')
})
}).then(resp => {
console.log(resp);
}, err => {
console.log(err);
})
Promise.prototype.then()多次调用处理
上面我们对promise里面存在异步代码进行了处理,接着我们对多次调用进行处理 什么是多次调用的?
let promise = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve('成功')
})
})
promise.then(resp => {
console.log(1);
console.log(resp);
})
promise.then(resp => {
console.log(2);
console.log(resp);
})
promise.then(resp => {
console.log(3);
console.log(resp);
})
上述这段代码如果我们采用上面的MyPromise执行的话,我们输出的数字打印只会打印1,原因就是我们successCllback和failCallback只临时保存了一次,所以只会保存我们的第一个then的返回值。接下来我们开始完善我们的MyPromise
- 我们需要保存所有的调用回调函数,那么successCallback和failCallback就需要是个数组
- 将所有的回调函数push进临时存储数组
- 依次循环临时存储的数组,执行一个就删除一个
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise {
constructor(executor) {
executor(this.resolve, this.reject)
}
status = PENDING
resp = undefined
error = undefined
//1. 更改临时存储为数组
successCallback = []
failCallback = []
resolve = (resp) => {
if (this.staus !== PENDING) return
this.status = FULFILLED
this.resp = resp
// this.successCallback && this.successCallback(this.resp)
//3. 依次循环临时保存数组,执行完一个就弹出一个,并将返回值返回
while (this.successCallback.length) this.successCallback.shift()(this.resp)
}
reject = (error) => {
if (this.staus !== PENDING) return
this.status = REJECTED
this.error = error
// this.failCallback && this.failCallback(this.error)
while (this.failCallback.length) this.failCallback.shift()(this.error)
}
then(successCallback, failCallback) {
if (this.status === FULFILLED) {
successCallback(this.resp)
} else if (this.status === REJECTED) {
failCallback(this.error)
} else {
//2. 将回调函数一次push进入临时保存数组
this.successCallback.push(successCallback)
this.failCallback.push(failCallback)
}
}
}