前言:
- 使用await的前提是函数被async修饰
- 被async修饰的函数,调用这个函数会得到一个promise,若函数无返回值,promise的result就是undefined
- try catch只能捕获同步错误,不能捕获异步错误,这是写代码常见的忽略点,下文可以见到。
- 代码中错误处理了,就不算错误了,代码就会往下面跑,不处理错误代码就停住了,不跑了。
文章讨论的问题:await的使用及错误处理
文章涵盖的情况:
1.await修饰同步代码函数
2.await修饰异步代码函数
3.await修饰return new Promise包裹的同步代码函数
4.await修饰return new Promise包裹的异步代码函数
5.await修饰return new Promise包裹的异步代码函数阻塞程度
6.最外层函数catch捕获await里面的reject****不捕获异步错误
1.await一个不返回promise的函数,函数中有异步函数且异步函数出错。
function tu(){
setTimeout(()=>{
let a="1"
let b=a.l.j//错误位置
},5000)
}
async function yo(){
await tu()
console.log("tu后")
}
function jk(){
console.log("jk")
}
yo().catch((e)=>{
console.log("出错了",e)
})
jk()
console.log("haha")
jk//jk调用和yo调用在同等位置jk却先输出
haha//haha输出都比“tu后”输出早,难道函数被async,await修饰之后,"tu后输出慢了"?这个点,在第2点叙述。
tu后//先输出了await后面的tu后
Promise {<resolved>: undefined}//再返回了一个promise,catch也没有捕获到错误
Uncaught TypeError: Cannot read property 'j' of undefined//最后报了错误
2.await一个不返回promise的函数,函数中有同步函数且同步函数出错。
小tip: 难道函数被async,await修饰之后,函数的执行就变慢了?
function tu(){
let a="1"
let b=a.l.j
}
async function yo(){
await tu()
console.log("tu后")
}
function jk(){
console.log("jk")
}
yo().catch((e)=>{
console.log("出错了",e)
})
jk()
console.log("fdas")
jk
fdas//从这里可以看出,async和await修饰的函数,执行确实变慢了。
出错了 TypeError: Cannot read property 'j' of undefined//(1)await后面的同步函数出错了,后面的“tu后”就没有输出,且被yo最外面的catch捕获到了错误。(2)结合第1点来看,await修饰了一个异步函数,如果这个异步函数里面出错了,那么await不会去等着个错误,而是执行了后面的同步代码,且yo最外面的catch捕获不到里面的错误。
两个点的小结:(1)await非Promise的函数:同步报错被中断,异步函数不中断。同步最外层函数可catch,异步函数最外层catch不到。(2)有wait的函数,看似写法是同步,不论wait同步还是异步,函数的执行被靠后。
3.await一个返回promise的函数,函数中有异步函数且异步函数出错。
function tu(){
return new Promise((resolve,reject)=>{
try{//在前言中就说过,这是写捕获错误的常见错误,try catch 去捕获异步的错误根本是捕获不到的,写了等于白写。
setTimeout(()=>{
let a="1"
let b=a.l.j//错误位置
resolve()
},5000)
}catch(e){
reject(e)
}
})
}
async function yo(){
await tu()
console.log("tu后")//没有输出
}
yo().catch(()=>{console.log("出错了")})//出错了没有输出,可见最外层捕获不到await里面的函数,但是不同于1,它拦住了异步,确实拦住了异步,下面代码可以加强await return Promise包裹异步,可以拦截异步。
Promise {<pending>}
Uncaught TypeError: Cannot read property 'j' of undefined
await return Promise包裹异步,可以拦截异步,等待异步执行完成后,再执行后面的代码。
由1和3点可见await要想拦截阻塞住异步函数,那么await的函数中的异步代码要用retrun new Promise进行包裹。
function tu(){
return new Promise((resolve,reject)=>{
try{
setTimeout(()=>{
let a="1"
resolve('')
},5000)
}catch(e){
reject(e)
}
})
}
async function yo(){
await tu()
console.log("tu后")
}
yo().catch(()=>{console.log("出错了")})
Promise {<pending>}
tu后//异步没报错,这个就输出了
4.await一个返回promise的函数,函数中有同步函数且同步函数出错。
function tu(){
return new Promise((resolve,reject)=>{
try{
let a="1"
let b=a.l.j//错误位置
resolve()
}catch(e){
reject(e)
}
})
}
async function yo(){
await tu()
console.log("tu后")//没有输出,可见await return promise包裹同步代码是可以阻塞代码的
}
yo().catch(()=>{console.log("出错了")})
出错了//await return promise包裹同步代码最外层可以捕获错误
Promise {<resolved>: undefined}
5.await await的连环套用
function tu(){
return new Promise((resolve,reject)=>{
try{
setTimeout(()=>{
let a="1"
resolve('')
},5000)
}catch(e){
reject(e)
}
})
}
async function yo(){
await tu()
console.log("tu后")
}
async function lp(){
await yo()
console.log("yoyo")
}
lp().catch(()=>{console.log("出错了")})
console.log("fdsfas")
fdsfas
tu后
yoyo//可见await的连环套用阻塞是生效的
6.上面的catch之所以捕获不到错误,实际上是try catch只能捕获同步错误,不能捕获异步错误
小tip 异步
try{
setTimeout(()=>{
let a="1"
let b=a.l.j//错误位置
},5000)
}catch(e){
console.log("出错了")//未输出,没有捕获到错误
}
Uncaught TypeError: Cannot read property 'j' of undefined
小tip 同步
setTimeout(()=>{
try{
let a="1"
let b=a.l.j//错误位置
}catch(e){
console.log("出错了")//输出了
}
},5000)
出错了
7.await修饰函数return new Promise包裹异步代码的阻塞程度
function tu(){
return new Promise((resolve,reject)=>{
try{
setTimeout(()=>{
jjj()
},5000)
}catch(e){
reject(e)
}
})
}
async function yo(){
await tu()
console.log("tu后")//没有输出,说明await会等待return promise中的所有函数执行完,这就是程度。
}
function jjj(){
setTimeout(()=>{
let a="1"
let b=a.l.j//错误位置
},5000)
}
yo().catch(()=>{console.log("出错了")})
Uncaught TypeError: Cannot read property 'j' of undefined
8.await 函数return new Promise包裹第三方函数
function tu(){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
jjj()
},5000)
}).catch((e)=>{console.log("错误位置",e)})//捕获不到异不函数错误,除非有reject指明
}
async function yo(){
await tu()
console.log("tu后")//没有输出,可见await中如果第三方函数有错误就会被阻塞,这和阻塞程度有关系。
}
function jjj(){//第三方函数
setTimeout(()=>{
let a="1"
let b=a.l.j//错误位置
},5000)
}
let a=yo().catch(()=>{console.log("出错了")})
9.最外层catch只能捕获await内部reject,不能捕获错误
小tip 没有捕获到错误
function tu(){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
let a="1"
let b=a.l.j//错误位置
},5000)
})
}
async function yo(){
await tu()
console.log("tu后")//没有输出
}
yo().catch(()=>{console.log("出错了")})
Promise {<pending>}
Uncaught TypeError: Cannot read property 'j' of undefined
小tip 捕获到reject
function tu(){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
reject("fdsfas")
},5000)
})
}
async function yo(){
await tu()
console.log("tu后")//没有输出
}
yo().catch(()=>{console.log("出错了")})
Promise {<pending>}
出错了
10.try catch 是可以捕获reject的
async function f4() {
try {
await new Promise((resolve,reject)=>{reject(30)})
} catch (e) {
console.log(e); // 30
}
}
f4();
30