JS Promise使用注意事项
- 前言
- 一、finally使用
- 二、错误捕获
- 2.1 .cath捕获
- 2.2 try catch捕获
- 三、Promise方法内使用return
- 3.1 前置return
- 3.2 后置return
- 四 no-async-promise-executor
- 五、no-await-in-loop
前言
对于js而言,我们平时使用promise情况是十分常见的 ,然而有些地方并没有很好地使用,这篇文章介绍常见的promise不规范示范和正确使用方式。
一、finally使用
通常开发过程中,我们页面都有loading,使用Promise前开启loading,结束的时候关闭loading。但有些小伙伴会在then和catch里面结束,这样不够优雅,其实最好是在finally里面结束。
正确示范:
let isLoading = trueconst result = await promiseSuccess().finally(() => {isLoading = false})
二、错误捕获
错误捕获可以使用.catch 和try catch,二者是由区别的,最大区别是try catch只要捕获到一个错误就会中断后续代码,但.catch不会,需要结合resolve结果来中断代码。
现在我们拥有2个方法
- promiseSuccess(),
该方法100%返回resolve(true)
- promiseFail(),
该方法100%返回reject(new Error("出错了"))
/** promise成功 */
function promiseSuccess() {return new Promise((resolve) => {resolve(true)})
}/** promise失败 */
function promiseFail(errorStr = '出错了') {return new Promise((resolve, reject) => {reject(new Error(errorStr))})
}
2.1 .cath捕获
console.log(1)await promiseSuccess().catch((error) => {console.log(error)})console.log(2)await promiseFail().catch((error) => {console.log(error)})console.log(3)
- 执行上述代码,结果是
1
2
Error: 出错了
3
通常我们是发生错误的时候需要中断代码执行
,那么需要结合resolve结果来判断是否要中断代码,正确写法是
console.log(1)const result1 = await promiseSuccess().catch((error) => {console.log(error)})if (!result1) returnconsole.log(2)const result2 = await promiseFail().catch((error) => {console.log(error)})if (!result2) returnconsole.log(3)
- 执行上述代码,结果是
1
2
Error: 出错了
2.2 try catch捕获
上述代码好像有点啰嗦,所以我们可以用try catch,正确代码:
try {console.log(1)const result1 = await promiseSuccess()console.log(2)const result2 = await promiseFail()console.log(3)} catch (error) {console.log(error)}
- 执行上述代码,结果是
1
2
Error: 出错了
三、Promise方法内使用return
首先,Promise方法内使用return是不建议的,如果有用eslint,那么会提示 no-return-await
,我们看看如果用return会由什么结果
3.1 前置return
- 修改方法promiseSuccess,会在
resolve前
执行return
/** promise成功 */
function promiseSuccess() {return new Promise((resolve) => {return 'return'resolve(true)})
}
- 测试程序
console.log(1)const result = await promiseSuccess().catch((error) => {console.log(error)
})
console.log('result', result)
if (!result) returnconsole.log(2)
- 执行上述代码,结果是
1
- 原因分析:由于promiseSuccess没有执行到resolve,所以await一直在等待,程序不会往下处理。
3.2 后置return
- 修改方法promiseSuccess,会在
resolve后
执行return
/** promise成功 */
function promiseSuccess() {return new Promise((resolve) => {resolve(true)return 'return'})
}
- 测试程序设上面一致
- 执行上述代码,结果是
1
result true
2
- 原因分析:
await只会获取resolve结果,里面的return值并没有影响
。
四 no-async-promise-executor
不建议将 async 函数传递给 new Promise 的构造函数;
如果下面代码,如果有用eslint会提示 no-async-promise-executor,原因是async本来是异步的,就无必要嵌套在Promise里面了。
- 代码示范
// 错误示范:
function promiseTest() {return new Promise(async (resolve) => {const result = await promiseSuccess()resolve(result)})
}// 正确示范1:
async function promiseTest() {const result = await promiseSuccess()return result
}// 正确示范2,如果硬要使用Promise,那么可以这样:
async function promiseTest() {const result = await promiseSuccess()return new Promise((resolve) => {resolve(result)})
}
- 使用方式都一样
const result1 = await promiseTest().catch((error) => {console.log(error)
})
console.log('result1', result1)
五、no-await-in-loop
不建议在循环里使用 await,有这种写法通常意味着程序没有充分利用 JavaScript 的事件驱动。
通常情况下可以使用Promise.all 代替。
- 示范代码:
// 错误示范:
async function foo(things) {const results = [];for (const thing of things) {results.push(await bar(thing));}return baz(results);
}// 正确示范:
async function foo(things) {const results = [];for (const thing of things) {results.push(bar(thing));}return baz(await Promise.all(results));
}
但是,如果每一次循环都需要改变数据,并且这个数据会带入到下次循环里,这种情况是可以使用循环里嵌套await的!