关于catch的同步和异步,还有try catch

在同步代码和异步代码中错误的捕获机制是不一样的,如果忽视这点只是简单的加 try…catch可能会忽视某些错误的捕获。本篇代码已经抽象为极简模式,可以多try try看看效果,既能理解错误捕获还可以理解任务执行机制

可以先看看对 JavaScript 中的 try-catch 能否捕获异步错误的探究 前置了解

同步错误捕获

先看看下面的这段代码

function testA(obj) { 
	const a = obj.a;
	return a;
}

function testB(input){ 
	try{
	    const res = testA(input)
	    console.log('BBB', res);
	} catch(e) {
    	console.error('同步错误捕获')
    }
}

testB(null)
testB({})

最后控制台打印输出
在这里插入图片描述
分析:当执行testB(null)代码执行testA函数时会报错,从而被catch住;而执行testB({})的时候则正常执行打印

异步错误捕获

当异步任务重嵌套的同步任务能捕获到吗?

先看看下面的这段代码

function testA(obj) { 
	const a = obj.a;
	return a;
}

function testB(input){ 
    let res;
	new Promise(() => {
		res = testA(input);
		}).then(() => {
			console.log('BBB', res);
		}).catch((e) => {
			console.error('捕获到了整个promise里面的错误')
		})
    console.log('CCC', res);
}

testB(null)
testB({})

可以看出是先执行同步任务testB(null) 打印同步任务CCC Promise放入微任务队列
执行同步任务testB({}),Promise 没有 resolve 或 reject,因此 then 和 catch 中的代码不执行。打印同步任务CCC
同步任务执行完,查看任务队列发现Promise取出微任务Promise执行
接着执行Promise微任务 这时候执行微任务的时候遇到了里面的同步任务testA,这样即便同步任务testA里面有错误,也会被Promise那层的catch住,因此打印了“捕获到了整个promise里面的错误”
在这里插入图片描述

或许上面代码让你有点乱,可以使用async 和 await 的语法糖构建成同步形式就好看啦

function testA(obj) { 
	const a = obj.a;
	return a;
}

async function testB(input){ 
    let res;
	await new Promise(() => {
		res = testA(input);
		console.log('AAA', res);
		}).then(() => {
			console.log('BBB', res);
		}).catch((e) => {
			console.error('捕获到了整个promise里面的错误')
	})
    console.log('CCC', res);
}

 testB(null)
// testB({})

执行同步任务testB(null)的 await同步语法糖等待Promise执行
执行testA,因此catch输出"捕获到了整个promise里面的错误",然后打印CCC,至此整个Promise成fulfilled。
如果这里没有await,那就先打印CCC啦,再走Promise 然后 catch 住错误

在这里插入图片描述
而执行testB({}) 中执行完res = testA(input); 我没有进行resolve 因此一直处于pending状态,await 会暂停函数执行,等待后面的 Promise 解决(resolve 或 reject)。因此也不会打印CCC了,到不了那里了
在这里插入图片描述

倘若await则全看成同步代码输出就好,testB会结束
在这里插入图片描述
在这里插入图片描述

跑题了,不是来看同步异步的,我们是看异常捕获的!!!感兴趣的小伙伴自行学习

同步异步错误同时捕获

上面已经可以看到,在异步里面的同步错误,是可以被最外层的异步任务的catch捕获到的,所以有时候我们不需要写很多try catch

那同步任务和异步任务同时都有的时候怎么办呢?例如下面的一段代码

function testA(obj) { 
	const a = obj.a;
	return a;
}

function testC(obj) { 
	const b = obj.b;
	return b;
}

async function testB(input1, input2){ 
    let res;
    res = testC(input2);
	await new Promise(() => {
		res = testA(input1);
		console.log('AAA', res);
		}).then(() => {
			console.log('BBB', res);
		}).catch((e) => {
			console.error('捕获到了整个promise里面的错误')
	})
   	console.log('CCC', res);
}

testB(null, null)

这样就丸辣,因为同步任务并没有catch住(这里仔细看看有几个同步代码~)
在这里插入图片描述

因此,要搭配try catch 捕获同步异常

function testA(obj) { 
	const a = obj.a;
	return a;
}

function testC(obj) { 
	const b = obj.b;
	return b;
}

async function testB(input1, input2){ 
    let res;
    try{
	    res = testC(input2);
		await new Promise(() => {
			res = testA(input1);
			console.log('AAA', res);
			}).then(() => {
				console.log('BBB', res);
			}).catch((e) => {
				console.error('捕获到了整个promise里面的错误')
		})
    	console.log('CCC', res);
    } catch (e) {
    	console.error('捕获同步错误')
    }
}

testB(null, null)
// testB(null, {})
// testB({}, null)
// testB({})

可以看出,最外层的同步错误已经catch了,内层的错误不会再报了而直接fulfilled

在这里插入图片描述

有童鞋说这样也太冗余了,一会儿try catch 一会儿catch,那就最外层加一个就好了嘛,是不是一起就捕获了

function testA(obj) { 
	const a = obj.a;
	return a;
}

function testC(obj) { 
	const b = obj.b;
	return b;
}

async function testB(input1, input2){ 
    let res;
    try{
	    res = testC(input2);
		await new Promise(() => {
			res = testA(input1);
			console.log('AAA', res);
			}).then(() => {
				console.log('BBB', res);
			})
			// .catch((e) => {
			//	 console.error('捕获到了整个promise里面的错误')
		// })
    	console.log('CCC', res);
    } catch (e) {
    	console.error('捕获同步错误')
    }
}

testB(null, null)

在这里插入图片描述
看起来没问题嘛,还是,当只有里面出问题的时候还是捕获了。你再仔细看看呢,由于加了await语法糖,实际上你这个是同步代码!!!所以同步代码均被外面的try catch捕获了。所以上面让看看有几个同步代码~
真实的场景是这样的同步夹杂异步,也就是去掉await async语法糖
在这里插入图片描述
看这样是不是没有捕获住??

如果外面同步代码没问题,而内部代码出问题则会被内部的捕获,所以是没问题的,到谁那儿捕获谁嘛,虽然使用了await语法糖,但是内层对异步处理的catch仍然捕获到了!!!主打一个就近原则

在这里插入图片描述
这时你把await去掉成异步也没问题的
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lanmy_dl

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值