错误写法1:使用catch捕获非await方式调用的async函数中抛出的Error:
async function func() {
throw new Error('error');
}
try {
func();
} catch(e) {
console.error(e.message);
}
导致后果1:未能捕获Error,且产生未处理promise rejection:
出错原因1:根据"Async function will return a Promise which will be rejected with an exception thrown from, or uncaught within, the async function",throw抛出Error使得func返回Promise { <rejected> Error: error },未处理Promise { <rejected> Error: error }导致UnhandledPromiseRejectionWarning。
async function func() {
throw new Error('error');
}
console.log(func());
正确写法1.1: 在可能抛出Error的函数内使用 try/catch 结构:
async function func() {
try {
throw new Error('error');
} catch(e) {
console.error(e.message);
}
}
func();
运行结果1.1:
正确写法1.2:在调用可能抛出Error的函数的末尾链接.catch() 块:
async function func() {
throw new Error('error');
}
func()
.catch(e => {
console.error(e.message);
});
运行结果1.2:
正确写法1.3:以await方式调用可能抛出Error的函数:
async function func() {
throw new Error('error');
}
(async function() {
try {
await func();
} catch(e) {
console.error(e.message);
}
})();
运行结果1.3:
错误写法2:使用catch处理非await方式调用的async函数中返回的promise rejection:
async function func() {
return await Promise.reject('reason');
}
try {
func();
} catch(e) {
console.error(e);
}
导致后果2:未能处理promise rejection:
出错原因2:
- func异步非阻塞执行立即返回Promise { <pending> };
- 随后Promise { <pending> }异步返回生成Promise { <rejected> 'reason' };
- catch无法捕获Promise { <rejected> 'reason' }。
async function func() {
return await Promise.reject('reason');
}
console.log(func());
正确写法2.1: 在可能返回promise rejection的函数内使用try/catch结构:
async function func() {
try {
return await Promise.reject('reason');
} catch(e) {
console.error(e);
}
}
func();
运行结果2.1:
正确写法2.2:在调用可能返回promise rejection的函数的末尾链接.catch() 块:
async function func() {
return await Promise.reject('reason');
}
func()
.catch((e) =>
console.error(e)
);
运行结果2.2:
正确写法2.3:以await方式调用可能返回promise rejection的函数:
async function func() {
return await Promise.reject('reason');
}
(async function() {
try {
await func();
} catch(e) {
console.error(e);
}
})();
运行结果2.3:
错误写法3.1:用try/catch处理promise rejection;
错误写法3.2:用throw抛出promise rejection:
function func() {
throw Promise.reject('reason');
}
try {
func();
} catch(e) {
console.error(e);
}
导致后果3:未能处理promise rejection:
出错原因3:try...catch捕获了promise rejection不代表处理了promise rejection。
错误改法3:
async function func() {
await Promise.reject('reason');
}
try {
func();
} catch(e) {
console.error(e);
}
运行结果3:未能处理promise rejection:
改错原因3:func异步非阻塞执行立即返回Promise { <pending> },随后异步返回Promise { <rejected> 'reason' },却未设置处理Promise { <rejected> 'reason' }的语句。
正确写法3.1:先使用async/await将异步promise rejection转换成同步代码的风格,再使用同步 try/catch 结构。
async function func() {
await Promise.reject('reason');
}
(async () => {
try {
await func();
}
catch(e) {
console.error(e);
}
})();
运行结果3.1:
优化写法3.2:
async function func() {
try {
await Promise.reject('reason');
} catch(e) {
console.error(e);
}
}
func();
运行结果3.2:
Note: .then()/.catch() blocks in promises are basically the async equivalent of a try...catch block in sync code. Bear in mind that synchronous try...catch won't work in async code.
错误写法4:使用.catch捕获非async函数中throw抛出的promise rejection:
function func() {
throw Promise.reject('reason');
}
func()
.catch(console.error);
导致后果4:语法错误:
正确写法4:
async function func() {
await Promise.reject('reason');
}
func()
.catch(console.error);
运行结果4:
错误写法5:在保存await语句返回值的变量的末尾链接.then()或.catch() 块:
async function func() {
let p = await new Promise(function(resolve,) {
setTimeout(() => resolve('value'), 1000);
});
p
.then(console.log)
.catch(console.error);
}
func();
导致后果5:TypeError:
错误原因5:await语句返回的是Promise resolved后携带的值,而不是Promise本身。
正确写法5:
async function func() {
let p = await new Promise(function(resolve,) {
setTimeout(() => resolve('value'), 1000);
});
console.log(p);
}
func()
.catch(console.error);
运行结果5:
编程细则1:
If the Promise is rejected, only the await expression throws the rejected value.
/* test1 */
function func() {
Promise.reject('reason');
}
func()
.catch(console.error); // TypeError: Cannot read property 'catch' of undefined
/* test2 */
function func() {
Promise.reject('reason'); // UnhandledPromiseRejectionWarning: reason
}
try {
func();
} catch(e) {
console.error(e);
}
/* test3 */
async function func() {
Promise.reject('reason'); // UnhandledPromiseRejectionWarning: reason
}
func()
.catch(console.error);
/* test4 */
async function func() {
Promise.reject('reason'); // UnhandledPromiseRejectionWarning: reason
}
try {
func();
} catch(e) {
console.error(e);
}
/* test5 */
async function func() {
await Promise.reject('reason');
}
func()
.catch(console.error); // reason
/* test6 */
async function func() {
await Promise.reject('reason');
}
try {
func(); // UnhandledPromiseRejectionWarning: reason
} catch(e) {
console.error(e);
}
编程细则2.1:普通函数中Promise.reject语句不会停止当前函数的执行:
function func() {
console.log(11111);
Promise.reject('reason');
console.log(22222);
}
func()
.catch(console.error);
/*
11111
22222
/mnt/hgfs/shared_folder/test.js:8
.catch(console.error);
^
TypeError: Cannot read property 'catch' of undefined
*/
编程细则2.2:如果Promise被拒绝,则await表达式会抛出被拒绝的值,若该值在当前函数内未被捕获,则停止当前函数的执行:
async function func() {
console.log(11111);
await Promise.reject('reason');
console.log(22222);
}
func()
.catch(console.error);
/*
11111
reason
*/
编程细则2.3:如果Promise被拒绝,则await表达式会抛出被拒绝的值,若该值在当前函数内被捕获,则继续当前函数的执行:
async function func() {
console.log(11111);
await Promise.reject('reason')
.catch(console.error);
console.log(22222);
}
func();
/*
11111
reason
22222
*/
编程细则3:不能省略return后的await。
保留return后的await,func稍后返回null;
省略return后的await,func立即返回Promise { <pending> }。
async function func() {
try {
return await Promise.reject('reason');
} catch (e) {
return null;
}
}
(async function() {
console.log(await func());
})();
编程细则4:若func的参数依赖于同步阻塞函数的执行结果,则func同步阻塞执行。
async function func1() {
return await Promise.resolve('222');
}
async function func2() {
return await Promise.resolve('22');
}
(async function() {
console.log('11111');
console.log(await func1() + await func2());
console.log('33333');
})();
/*
11111
22222
33333
*/