zoukankan      html  css  js  c++  java
  • JavaScript(七)错误处理

    错误传播

    如果代码发生了错误,又没有被try ... catch捕获,那么,程序执行流程会跳转到哪呢?

    function getLength(s) {
        return s.length;
    }
    
    function printLength() {
        console.log(getLength('abc')); // 3
        console.log(getLength(null)); // Error!
    }
    
    printLength();

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

    所以,我们不必在每一个函数内部捕获错误,只需要在合适的地方来个统一捕获,一网打尽:

    'use strict';
    function main(s) {
        console.log('BEGIN main()');
        try {
            foo(s);
        } catch (e) {
            console.log('出错了:' + e);
        }
        console.log('END main()');
    }
    
    function foo(s) {
        console.log('BEGIN foo()');
        bar(s);
        console.log('END foo()');
    }
    
    function bar(s) {
        console.log('BEGIN bar()');
        console.log('length = ' + s.length);
        console.log('END bar()');
    }
    
    main(null);
    
    
    /*运行结果:
    BEGIN main()
    BEGIN foo()
    BEGIN bar()
    出错了:TypeError: Cannot read property 'length' of null
    END main()
    */

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

    至于在哪些地方捕获错误比较合适,需要视情况而定。

    异步错误处理

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

    例如,setTimeout()函数可以传入回调函数,并在指定若干毫秒后执行

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

    上面的代码会先打印done,1秒后才会打印It is time!

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

    'use strict';
    function printTime() {
        throw new Error();
    }
    
    try {
        setTimeout(printTime, 1000);
        console.log('done');
    } catch (e) {
        console.log('error');
    }

    //运行结果
    //done

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

    所以,涉及到异步代码,无法在调用时捕获,原因就是在捕获的当时,回调函数并未执行。

    类似的,当我们处理一个事件时,在绑定事件的代码处,无法捕获事件处理函数的错误。

    例如,针对以下的表单:

    <form>
        <input id="x"> + <input id="y">
        <button id="calc" type="button">计算</button>
    </form>

    对当前的内容进行计算方式如下:

    $btn.click(function () {
    
    try {
    
            var
    
                x = parseFloat($('#x').val()),
    
                y = parseFloat($('#y').val()),
    
                r;
    
            if (isNaN(x) || isNaN(y)) {
    
                throw new Error('输入有误');
    
            }
    
            r = x + y;
    
            alert('计算结果:' + r);
    
    }
    声明 欢迎转载,但请保留文章原始出处:) 博客园:https://www.cnblogs.com/chenxiaomeng/ 如出现转载未声明 将追究法律责任~谢谢合作
  • 相关阅读:
    MyBatis进阶(一)
    git命令整理
    今天的任务--git练习
    深入浅出JavaScript(一)
    数据结构_树_二叉搜索树
    网络_体系结构
    数据结构_树
    算法_五大经典搜索算法
    SpringMVC入门
    spring 线程异步执行
  • 原文地址:https://www.cnblogs.com/chenxiaomeng/p/15177574.html
Copyright © 2011-2022 走看看