javascript学习笔记(6)--错误传播&异步错误处理

如果在一个函数内部发生了错误,它自身没有捕获,错误就会被抛到外层调用函数,如果外层函数也没有捕获,该错误会一直沿着函数调用链向上抛出,直到被JavaScript引擎捕获,代码终止执行

function getLength(s)
{ return s.length; };//返回长度
  function printLength() 
{ console.log(getLength('abc'));  console.log(getLength(null));
}
printLength();
3 
TypeError: s is null//现在控制台返回了abc的长度,然后报错

因为每个函数都没有错误处理,所以最后直接由javascript捕获进而报错

同时,我们不必在每一个函数内部捕获错误,只需要在合适的地方来个统一捕获,一网打尽,至于在哪些地方捕获错误比较合适,需要视情况而定

function main(s)
 { 
 console.log('开始main()');
  try {foo(s); } 
  catch (e) { alert('出错了:' + e); }
  console.log('结束main()');
};
  function foo(s)
   { 
 console.log('开始 foo()');
  bar(s);
 console.log('结束 foo()');
  };
function bar(s) 
{ 
console.log('开始bar()'); 
console.log('length = ' + s.length);
 console.log('结束 bar()'); };
 main(null); 
 开始main() 
开始 foo() 
开始bar()
出错了:TypeError: s is null

这里是在最上层函数里加了错误处理,main调用foo,foo调用bar
当bar()函数传入参数null时,代码会报错,错误会向上抛给调用方foo()函数,foo()函数没有try …catch语句,所以 错误继续向上抛给调用方main()函数,main()函数有try …catch语句,所以错误最终在main()函数被处理了

JavaScript引擎是一个事件驱动的执行引擎,代码总是以单线程执行,而回调函数的执行需要等到下一个满足条件的事件出现后,才会被执行

setTimeout()是个很特别的函数,其他的函数都是要按着次序依次执行,而这个函数内的回调函数会在设置了若干毫秒后执行,并且一旦设置号时间后,会继续往下执行,不会等着回调函数
所以在含有setTimeout代码里可能看到setTImeout后面的代码可能会先执行

function printTime() 
{ console.log('It is time!'); }
setTimeout(printTime, 1000); 
console.log('done'); 
done 
It is time!

跟我说的一样吧,先打印了done,再过1秒打印it is time

如果printTime()函数内部发生了错误,我们试图用try包裹setTimeout()是无效的,不信来尝试一下

 function printTime()
  { throw new Error(); }
 try {
 setTimeout(printTime, 1000); 
 console.log('done');
  } 
 catch (e) { alert('error'); }
 //并没有alert

原因就在于调用setTimeout()函数时,传入的printTime函数并未立刻执行,紧接着,JavaScript引擎会继续执行console.log('done');语句,而此时并没有错误发生,直到1秒钟后,执行printTime函数时才发生错误,但此时printTime函数内部并不能捕获错误,外层代码也无法捕获

所以,涉及到异步代码,无法在调用时捕获,原因就是在捕获的当时,回调函数并未执行
类似的,当我们处理一个事件时,在绑定事件的代码处,无法捕获事件处理函数的错误

<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-3.5.1.js"></script>
</head>
<body>
<form>
<input id="x"> + <input id="y"> 
<button id="calc" type="button">计算</button> 
</form>
<script>
function caculate()//定义了一个算加法的函数,并且如果输入不合法会抛出错误
{
var x = parseFloat($('#x').val());//把输入的x值转化为浮点数
var y = parseFloat($('#y').val());
var r;
if (isNaN(x) || isNaN(y))//如果出现字母,则oarseFload会返回Nan
 { throw new Error('输入有误'); }
else {r = x + y; alert('计算结果:' + r);}
}
var btn = $('#calc'); //绑定到按钮上
try
{
btn.on('click', caculate);//一旦提交就调用
}
catch (e) { alert('输入有误!'); }
</script>
</body>
</html>

上面这个代码可以正常执行计算,但如果遇到不合法输入时,并不会alert
因为当我们进入try语句后,一旦监听到click事件,就会去调用caculate函数,btn.on这句话就算执行完了,就开始捕捉error,但这个时候其实caculate还在运行,还没有throw error,所以catch也结束了,当真正error被抛过来之后,又没有外层捕捉函数了,所以最后javascript捕捉到了错误,报错在了控制台

下面是可以正确处理错误的代码

<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-3.5.1.js"></script>
</head>
<body>
<form>
<input id="x"> + <input id="y"> 
<button id="calc" type="button">计算</button> 
</form>
<script>
var btn = $('#calc'); 
btn.on('click', caculate);
function caculate(){
try {
var x = parseFloat($('#x').val());
var  y = parseFloat($('#y').val());
var r;
if (isNaN(x) || isNaN(y)){ throw new Error('输入有误'); }
else{r = x + y; alert('计算结果:' + r); }
}
catch (e) 
{ alert('输入有误!'); }
};
</script>
</body>
</html>

直接把计算过程放在try内部,就毫无问题啦

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值