实现Promise功能及其相关方法
概述
对于所有的前端开发人员来说,异步操作是工作中必不可少的一部分,在Promise还没有出现之前,多数为回调函数的方式解决,而Promise的出现,让异步操作变得更加优雅便利,因此,掌握Promise的使用是必不可少的,对于个人而言,Promise在开发中扮演如此重要角色,能够明白其实现机制,是对异步操作的更加深入认识,文章主要记录Promise的实现思路,本文Promise的用法我就不列举了,重点是实现思路。关于实现规范参阅Promises/A+
几个关键问题
1. Promise的几种状态?
- pending(等待)
- fulfilled(成功)
- rejected(失败)
2. Promise的状态怎么改变?
- resolve 函数调用,如果当前状态为pending,则会变成fulfilled。
- reject 函数调用,如果当前状态为pending,则会变成rejected。
- 抛出异常被try catch捕获的,如果当前状态为pending,则会变成rejected。
- promise的状态一旦由pending转变,则不可再次变更。
3. 一个promise指定多个成功/失败的回调,都会调用?
答案是会,例如:
//以下then函数的成功回调都会调用
let p = new Promise((resolve, reject) => {
resolve("成功")
})
p.then(res => {
console.log(res)
})
p.then(res => {
console.log(res)
})
p.then(res => {
console.log(res)
})
3. 改变promise状态和then函数指定的回调函数谁先谁后?
都有可能,正常情况是先指定回调,然后改变状态,反之也可以的。
- 如何先改变状态,再指定回调?
- 执行器函数中直接调用resolve或者reject。
- 延迟调用then函数直到状态已经变更。
- 什么时候得到结果?
- 如果先指定回调,则当状态变更的时候,会调用对应的回调,返回结果。
- 如果先改变状态,回调函数调用的时候,返回结果。
//先改状态
let p = new Promise((resolve, reject) => {
resolve("成功")
})
p.then(res => {
console.log(res)
})
//先指定回调
setTimeout(() => {
resolve("成功")
}, 200)
p.then(res => {
console.log(res)
})
4. promise.then()函数返回的新的promise的状态由什么决定?
简单来说就是then函数指定回调函数执行的结果返回值决定。 详解:
- 如果then指定的回调执行抛出异常,则新promise的状态变为rejected。
- 如果then指定的回调执行返回具体值或者undefined(非Promise类型),则新promise的状态变为fulfilled。
- 如果then指定的回调执行返回Promise类型,则新promise的状态由返回的Promise的状态决定。
let p = new Promise((resolve, reject) => {
resolve("成功")
})
//返回具体值情况
let p2 = p.then(res => {
console.log(res);
return 111;
})
console.log(p2)//成功的promise
//抛出异常
let p2 = p.then(res => {
console.log(res);
throw "1"
})
console.log(p2)//失败的promise
//返回值为promise
let p2 = p.then(res => {
console.log(res);
throw Promise.relve(1)
})
console.log(p2)//状态为成功的promise由 Promise.relve(1)的状态决定
5. promise如何串联多个操作任务?
- promise.then执行,返回一个的新的promise,可以实现链式调用。
- 通过then函数的链式调用执行串联任务。
6. promise异常穿透?
- 当使用promise的then链式调用的时候,可以在最后指定失败回调。
- 前面回调里面的任何异常,都会泡到最后的失败回调里面(层层往外抛)
7. promise中断promise链?
返回一个pending状态的Promise即可。
p.then(res => {
console.log(res)
}).then(res => {
console.log(res)
//返回pending状态的promise
return new Promise((resolve, reject) => { })
}).then(res => {
//不执行
console.log(res)
}).then(res => {
// 不执行
console.log(res)
})
具体实现过程
层层递进,从简单到复杂。
初始化机构搭建
基本结构
// 初始化三种状态,方便修改
const PENDING = "pending";
const FULFILLED = "fulfilled";
const RENECTED = "rejected";
class MyPromise {
constructor(executor) {
// 同步调用
executor(this.resolve.bind(this), this.reject.bind(this))
}
// then函数
then(onResolved, onRejected) {
}
// resolve函数
resolve(data) {
}
// reject函数
reject(data) {
}
}
// 实例化
let p = new MyPromise((resolve, reject) => {
})
resolve与reject代码实现
保证状态只能改变一次
// resolve函数
resolve(data) {
// 状态如果不是pending说明变更过了,因此不执行后续逻辑
if (this.status != PENDING) return;
this.status = FULFILLED;
this.fulfilledResult = data;
}
// reject函数
reject(data) {
// 状态如果不是pending说明变更过了,因此不执行后续逻辑
if (this.status != PENDING) return;
this.status = RENECTED;
this.rejectedResult = data;
}
// 实例化
let p = new MyPromise((resolve, reject) => {
// resolve("成功")
reject("失败")
reject("失败2")
})
throw抛出异常改变状态
通过try catch捕获,异常直接调用reject
constructor(executor) {
// 状态值
this.status = PENDING;
// 成功结果
this.fulfilledResult = null;
// 失败结果
this.rejectedResult = null;
// 同步调用(加上异常捕获)
try {
executor(this.resolve.bind(this), this.reject.bind(this))
} catch (e) {
// 异常直接调用reject
this.reject(e)
}
}
let p = new MyPromise((resolve, reject) => {
throw "111";
})
then方法执行回调
这一步只需要关注先更改状态,然后执行then回调的情况
// then函数
then(onResolved, onRejected) {
// 分三种状态:pending fulfilled rejected
switch (this.status) {
case PENDING:
// 暂定
break;
case FULFILLED:
// 状态改变且为fulfilled,调用成功的回调
onResolved(this.fulfilledResult);
break;
case RENECTED:
// 状态改变且为rejected,调用成功的回调
onRejected(this.rejectedResult);
break;
}
}
// 实例化
let p = new MyPromise((resolve, reject) => {
resolve("成功")
})
p.then((res) => {
console.log(res)
}, (err) => {
console.log(err)
})
异步任务回调的执行
实现异步更改promise的状态的情况,因此会先指定回调函数,因此初始为pending状态,只需要新增如下步骤。
constructor(executor) {
// // 状态值
// this.status = PENDING;
// // 成功结果
// this.fulfilledResult = null;
// // 失败结果
// this.rejectedResult = null;
// 成功的then回调
this.fulfilledCallback = null;
// 失败的then回调
this.rejectedCallback = null;
// // 同步调用(加上异常捕获)
// try {
// executor(this.resolve.bind(this), this.reject.bind(this));
// } catch (e) {
// // 异常直接调用reject
// this.reject(e);
// }
}
// then函数
then(onResolved, onRejected) {
// 分三种状态:pending fulfilled rejected
switch (this.status) {
case PENDING:
// 异步更改promis状态的情况,此时状态还为pending,保存对应的回调函数,等到状态变更后调用
this.fulfilledCallback = onResolved;
this.rejectedCallback = onRejected;
break;
// case FULFILLED:
// // 状态改变且为fulfilled,调用成功的回调
// onResolved(this.fulfilledResult);
// break;
// case RENECTED:
// // 状态改变且为rejected,调用成功的回调
// onRejected(this.rejectedResult);
// break;
}
}
// resolve函数
resolve(data) {
// // 状态如果不是pending说明变更过了,因此不执行后续逻辑
// if (this.status != PENDING) return;
// this.status = FULFILLED;
// this.fulfilledResult = data;
// 执行成功回调
this.fulfilledCallback && this.fulfilledCallback(this.fulfilledResult);
}
// reject函数
reject(data) {
// // 状态如果不是pending说明变更过了,因此不执行后续逻辑
// if (this.status != PENDING) return;
// this.status = RENECTED;
// this.rejectedResult = data;
// 执行失败回调
this.rejectedCallback && this.rejectedCallback(this.rejectedResult);
}
// 实例化
let p = new MyPromise((resolve, reject) => {
setTimeout(() => {
reject("成功")
}, 2000)
})
p.then((res) => {
console.log(res)
}, (err) => {
console.log(err)
})
指定多个回调的实现
实现当前promise可以指定多个回调的情况,目前我们实现的情况在状态异步更改情况下,不能执行所有的then指定的回调函数,改进如下
constructor(executor) {
// // 状态值
// this.status = PENDING;
// // 成功结果
// this.fulfilledResult = null;
// // 失败结果
// this.rejectedResult = null;
// then回调函数队列
this.thenCallbackList = [];
// // 同步调用(加上异常捕获)
// try {
// executor(this.resolve.bind(this), this.reject.bind(this));
// } catch (e) {
// // 异常直接调用reject
// this.reject(e);
// }
}
// then函数
then(onResolved, onRejected) {
// 分三种状态:pending fulfilled rejected
switch (this.status) {
case PENDING:
// 判断是否为函数,不是函数我们默认给一个空函数
onResolved = typeof onResolved == "function" ? onResolved : () => { };
onRejected = typeof onRejected == "function" ? onRejected : () => { };
this.thenCallbackList.push({
onResolved,
onRejected
})
break;
// case FULFILLED:
// // 状态改变且为fulfilled,调用成功的回调
// onResolved(this.fulfilledResult);
// break;
// case RENECTED:
// // 状态改变且为rejected,调用成功的回调
// onRejected(this.rejectedResult);
// break;
}
}
// resolve函数
resolve(data) {
// // 状态如果不是pending说明变更过了,因此不执行后续逻辑
// if (this.status != PENDING) return;
// this.status = FULFILLED;
// this.fulfilledResult = data;
if (this.thenCallbackList.length) {
// 循环调用
for (let i = 0; i < this.thenCallbackList.length; i++) {
this.thenCallbackList[i].onResolved(this.fulfilledResult)
}
}
}
// reject函数
reject(data) {
// // 状态如果不是pending说明变更过了,因此不执行后续逻辑
// if (this.status != PENDING) return;
// this.status = RENECTED;
// this.rejectedResult = data;
if (this.thenCallbackList.length) {
// 循环调用
for (let i = 0; i < this.thenCallbackList.length; i++) {
this.thenCallbackList[i].onRejected(this.rejectedResult)
}
}
}
// 实例化
let p = new MyPromise((resolve, reject) => {
setTimeout(() => {
reject("成功")
}, 2000)
})
p.then((res) => {
console.log(res)
}, (err) => {
console.log(err)
})
同步修改状态then方法结果返回
promise可以链式调用,因此,then函数执行,需要返回promise, 对返回结果处理,新的promise状态取决于回调的返回值,改进如下
// then函数
then(onResolved, onRejected) {
return new MyPromise((resolve, reject) => {
// 分三种状态:pending fulfilled rejected
switch (this.status) {
// case PENDING:
// // 判断是否为函数,不是函数我们默认给一个空函数
// onResolved = typeof onResolved == "function" ? onResolved : () => { };
// onRejected = typeof onRejected == "function" ? onRejected : () => { };
// this.thenCallbackList.push({
// onResolved,
// onRejected
// })
// break;
case FULFILLED:
// 状态改变且为fulfilled,调用成功的回调
let resolveRes = onResolved(this.fulfilledResult);
// 对返回结果处理,新的promise状态取决于回调的返回值,还要可能异常,进行捕获处理
try {
if (resolveRes instanceof MyPromise) {
resolveRes.then(res => {
resolve(res)
}, err => {
reject(err)
})
} else {
resolve(resolveRes)
}
} catch (e) {
reject(e)
}
break;
case RENECTED:
// 状态改变且为rejected,调用成功的回调
let rejectRes = onRejected(this.rejectedResult);
// 对返回结果处理,新的promise状态取决于回调的返回值,还要可能异常,进行捕获处理
try {
if (rejectRes instanceof MyPromise) {
rejectRes.then(res => {
resolve(res)
}, err => {
reject(err)
})
} else {
resolve(rejectRes)
}
} catch (e) {
reject(e)
}
break;
}
})
}
// 实例化
let p = new MyPromise((resolve, reject) => {
resolve("成功")
})
p.then((res) => {
console.log(res)
return "哈哈"
}, (err) => {
console.log(err)
}).then(res => {
console.log('链式' + res)
}, err => {
console.log(err)
}).then(res => {
console.log(res)
}, err => {
console.log(err)
})
异步修改状态then方法结果返回
思路和上面类似,只需要关注pending状态就欧克。
// then函数
then(onResolved, onRejected) {
return new MyPromise((resolve, reject) => {
// 分三种状态:pending fulfilled rejected
switch (this.status) {
case PENDING:
// 判断是否为函数,不是函数我们默认给一个空函数
onResolved = typeof onResolved == "function" ? onResolved : () => { };
onRejected = typeof onRejected == "function" ? onRejected : () => { };
this.thenCallbackList.push({
onResolved: () => {
let resolveRes = onResolved(this.fulfilledResult);
// 对返回结果处理,新的promise状态取决于回调的返回值,还要可能异常,进行捕获处理
try {
if (resolveRes instanceof MyPromise) {
resolveRes.then(res => {
resolve(res)
}, err => {
reject(err)
})
} else {
resolve(resolveRes)
}
} catch (e) {
reject(e)
}
},
onRejected: () => {
let rejectRes = onRejected(this.rejectedResult);
// 对返回结果处理,新的promise状态取决于回调的返回值,还要可能异常,进行捕获处理
try {
if (rejectRes instanceof MyPromise) {
rejectRes.then(res => {
resolve(res)
}, err => {
reject(err)
})
} else {
resolve(rejectRes)
}
} catch (e) {
reject(e)
}
}
})
break;
// case FULFILLED:
// // 状态改变且为fulfilled,调用成功的回调
// let resolveRes = onResolved(this.fulfilledResult);
// // 对返回结果处理,新的promise状态取决于回调的返回值,还要可能异常,进行捕获处理
// try {
// if (resolveRes instanceof MyPromise) {
// resolveRes.then(res => {
// resolve(res)
// }, err => {
// reject(err)
// })
// } else {
// resolve(resolveRes)
// }
// } catch (e) {
// reject(e)
// }
// break;
// case RENECTED:
// // 状态改变且为rejected,调用成功的回调
// let rejectRes = onRejected(this.rejectedResult);
// // 对返回结果处理,新的promise状态取决于回调的返回值,还要可能异常,进行捕获处理
// try {
// if (rejectRes instanceof MyPromise) {
// rejectRes.then(res => {
// resolve(res)
// }, err => {
// reject(err)
// })
// } else {
// resolve(rejectRes)
// }
// } catch (e) {
// reject(e)
// }
// break;
}
})
}
then函数优化处理
上面出现了太多的重复代码,这里抽离出去,是不是瞬间清爽多了。
// then函数
then(onResolved, onRejected) {
return new MyPromise((resolve, reject) => {
// 分三种状态:pending fulfilled rejected
switch (this.status) {
case PENDING:
// 判断是否为函数,不是函数我们默认给一个空函数
onResolved = typeof onResolved == "function" ? onResolved : () => { };
onRejected = typeof onRejected == "function" ? onRejected : () => { };
this.thenCallbackList.push({
onResolved: () => {
let resolveRes = onResolved(this.fulfilledResult);
// 对返回结果处理,新的promise状态取决于回调的返回值,还要可能异常,进行捕获处理
this.optimizedThenFn(resolveRes, resolve, reject)
},
onRejected: () => {
let rejectRes = onRejected(this.rejectedResult);
// 对返回结果处理,新的promise状态取决于回调的返回值,还要可能异常,进行捕获处理
this.optimizedThenFn(rejectRes, resolve, reject)
}
})
break;
case FULFILLED:
// 状态改变且为fulfilled,调用成功的回调
let resolveRes = onResolved(this.fulfilledResult);
// 对返回结果处理,新的promise状态取决于回调的返回值,还要可能异常,进行捕获处理
this.optimizedThenFn(resolveRes, resolve, reject)
break;
case RENECTED:
// 状态改变且为rejected,调用成功的回调
let rejectRes = onRejected(this.rejectedResult);
// 对返回结果处理,新的promise状态取决于回调的返回值,还要可能异常,进行捕获处理
this.optimizedThenFn(rejectRes, resolve, reject)
break;
}
})
}
// 优化then函数
optimizedThenFn(result, resolve, reject) {
try {
if (result instanceof MyPromise) {
result.then(res => {
resolve(res)
}, err => {
reject(err)
})
} else {
resolve(result)
}
} catch (e) {
reject(e)
}
}
catch方法-异常穿透与值传递
catch函数,本质上执行then回调,将第二回调传入即可,错误异常穿透记得throw一个错误,层层往外抛
// catch函数
catch(onRejected) {
return this.then(undefined, onRejected);
}
// then函数
then(onResolved, onRejected) {
// 判断是否为函数,不是函数我们默认给一个空函数
// onResolved = typeof onResolved == "function" ? onResolved : () => { };
// 这里可能会出现第二个参数不存在的问题,那么直接将错误往外面抛
onRejected = typeof onRejected == "function" ? onRejected : (err) => { throw err };
return new MyPromise((resolve, reject) => {
// 分三种状态:pending fulfilled rejected
switch (this.status) {
case PENDING:
this.thenCallbackList.push({
// onResolved: () => {
// let resolveRes = onResolved(this.fulfilledResult);
// // 对返回结果处理,新的promise状态取决于回调的返回值,还要可能异常,进行捕获处理
// this.optimizedThenFn(resolveRes, resolve, reject);
// },
onRejected: () => {
// 可能onRejected抛出异常,因此捕获错误
try {
let rejectRes = onRejected(this.rejectedResult);
// 对返回结果处理,新的promise状态取决于回调的返回值,还要可能异常,进行捕获处理
this.optimizedThenFn(rejectRes, resolve, reject);
} catch (err) {
reject(err)
}
}
})
break;
// case FULFILLED:
// // 状态改变且为fulfilled,调用成功的回调
// let resolveRes = onResolved(this.fulfilledResult);
// // 对返回结果处理,新的promise状态取决于回调的返回值,还要可能异常,进行捕获处理
// this.optimizedThenFn(resolveRes, resolve, reject);
// break;
case RENECTED:
// 可能onRejected抛出异常,因此捕获错误
try {
// 状态改变且为rejected,调用成功的回调
let rejectRes = onRejected(this.rejectedResult);
// 对返回结果处理,新的promise状态取决于回调的返回值,还要可能异常,进行捕获处理
this.optimizedThenFn(rejectRes, resolve, reject);
} catch (err) {
reject(err)
}
break;
}
})
}
let p = new MyPromise((resolve, reject) => {
setTimeout(() => {
reject("失败")
}, 2000)
})
p.then((res) => {
console.log(res)
}).then(res => {
console.log(res)
}).then(res => {
console.log(res)
}).catch(err => {
console.log("catch穿透捕获", err)
})
resolve方法封装
返回一个promise
// resolve
static resolve(value) {
return new MyPromise((resolve, reject) => {
if (value instanceof MyPromise) {
value.then(res => {
resolve(value)
}, err => {
reject(err)
})
} else {
resolve(value)
}
})
}
let res = MyPromise.resolve(1);
console.log(res)
reject方法封装
返回一个promise和resolve类似,不同在于不管什么参数类型,全部以失败处理。
// reject
static resolve(value) {
return new MyPromise((resolve, reject) => {
reject(value)
})
}
all方法封装
参数为promise对象数组,所有成功成功,一个失败则失败
static all(promiseList) {
return new MyPromise((resolve, reject) => {
let result = [];
let count = 0;
for (let i = 0; i < promiseList.length; i++) {
promiseList[i].then(res => {
count++;
result[i] = res;
if (count == promiseList.length) {
resolve(result)
}
}, err => {
reject([])
})
}
})
}
let p1 = new MyPromise((resolve, reject) => {
resolve(1)
})
let p2 = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve(2)
}, 3000)
})
let p3 = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve(3)
}, 1000)
})
let pall = MyPromise.all([p1, p2, p3])
pall.then(res => {
console.log(res)
})
race方法封装
龟兔赛跑,谁快,结果是谁
// race
static race(promiseList) {
return new MyPromise((resolve, reject) => {
for (let i = 0; i < promiseList.length; i++) {
promiseList[i].then(res => {
resolve(res)
}, err => {
reject(err)
})
}
})
}
let p1 = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve(1)
}, 4000)
})
let p2 = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve(2)
}, 3000)
})
let p3 = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve(3)
}, 1000)
})
let pall = MyPromise.race([p1, p2, p3])
pall.then(res => {
console.log(res)
})
完整代码
// 初始化三种状态,方便修改
const PENDING = "pending";
const FULFILLED = "fulfilled";
const RENECTED = "rejected";
class MyPromise {
constructor(executor) {
// 状态值
this.status = PENDING;
// 成功结果
this.fulfilledResult = null;
// 失败结果
this.rejectedResult = null;
// then回调函数队列
this.thenCallbackList = [];
// 同步调用(加上异常捕获)
try {
executor(this.resolve.bind(this), this.reject.bind(this));
} catch (e) {
// 异常直接调用reject
this.reject(e);
}
}
// then函数
then(onResolved, onRejected) {
// 判断是否为函数,不是函数我们默认给一个空函数
onResolved = typeof onResolved == "function" ? onResolved : () => { };
// 这里可能会出现第二个参数不存在的问题,那么直接将错误往外面抛
onRejected = typeof onRejected == "function" ? onRejected : (err) => { throw err };
return new MyPromise((resolve, reject) => {
// 分三种状态:pending fulfilled rejected
switch (this.status) {
case PENDING:
this.thenCallbackList.push({
onResolved: () => {
let resolveRes = onResolved(this.fulfilledResult);
// 对返回结果处理,新的promise状态取决于回调的返回值,还要可能异常,进行捕获处理
this.optimizedThenFn(resolveRes, resolve, reject);
},
onRejected: () => {
// 可能onRejected抛出异常,因此捕获错误
try {
let rejectRes = onRejected(this.rejectedResult);
// 对返回结果处理,新的promise状态取决于回调的返回值,还要可能异常,进行捕获处理
this.optimizedThenFn(rejectRes, resolve, reject);
} catch (err) {
reject(err)
}
}
})
break;
case FULFILLED:
// 状态改变且为fulfilled,调用成功的回调
let resolveRes = onResolved(this.fulfilledResult);
// 对返回结果处理,新的promise状态取决于回调的返回值,还要可能异常,进行捕获处理
this.optimizedThenFn(resolveRes, resolve, reject);
break;
case RENECTED:
// 可能onRejected抛出异常,因此捕获错误
try {
// 状态改变且为rejected,调用成功的回调
let rejectRes = onRejected(this.rejectedResult);
// 对返回结果处理,新的promise状态取决于回调的返回值,还要可能异常,进行捕获处理
this.optimizedThenFn(rejectRes, resolve, reject);
} catch (err) {
reject(err)
}
break;
}
})
}
// 优化then函数
optimizedThenFn(result, resolve, reject) {
try {
if (result instanceof MyPromise) {
result.then(res => {
resolve(res)
}, err => {
reject(err)
})
} else {
resolve(result)
}
} catch (e) {
reject(e)
}
}
// resolve函数
resolve(data) {
// 状态如果不是pending说明变更过了,因此不执行后续逻辑
if (this.status != PENDING) return;
this.status = FULFILLED;
this.fulfilledResult = data;
if (this.thenCallbackList.length) {
// 循环调用
for (let i = 0; i < this.thenCallbackList.length; i++) {
this.thenCallbackList[i].onResolved(this.fulfilledResult)
}
}
}
// reject函数
reject(data) {
// 状态如果不是pending说明变更过了,因此不执行后续逻辑
if (this.status != PENDING) return;
this.status = RENECTED;
this.rejectedResult = data;
if (this.thenCallbackList.length) {
// 循环调用
for (let i = 0; i < this.thenCallbackList.length; i++) {
this.thenCallbackList[i].onRejected(this.rejectedResult)
}
}
}
// catch函数
catch(onRejected) {
return this.then(undefined, onRejected);
}
// resolve
static resolve(value) {
return new MyPromise((resolve, reject) => {
if (value instanceof MyPromise) {
value.then(res => {
resolve(value)
}, err => {
reject(err)
})
} else {
resolve(value)
}
})
}
// reject
static resolve(value) {
return new MyPromise((resolve, reject) => {
reject(value)
})
}
// all
static all(promiseList) {
return new MyPromise((resolve, reject) => {
let result = [];
let count = 0;
for (let i = 0; i < promiseList.length; i++) {
promiseList[i].then(res => {
count++;
result[i] = res;
if (count == promiseList.length) {
resolve(result)
}
}, err => {
reject([])
})
}
})
}
// race
static race(promiseList) {
return new MyPromise((resolve, reject) => {
for (let i = 0; i < promiseList.length; i++) {
promiseList[i].then(res => {
resolve(res)
}, err => {
reject(err)
})
}
})
}
}
总结
其实promise里面的各种回调还是很多的,容易绕晕,停下来多想想就好了。
转载自:https://juejin.cn/post/7195763127883317309