JavaScript:如何使用在回调中抑制异常的库

javascript: how to work with libs that suppress exceptions in callbacks?

本文关键字:异常 回调 何使用 JavaScript      更新时间:2023-09-26

许多JavaScript库和框架接受在某些操作完成后调用的函数。例如:

chrome.storage.local.get( 'foo', function() { console.log( "foo" ); } );

但我刚刚意识到一些 API,包括上面提到的谷歌本地存储 API,会捕获并抑制正在调用的函数中的所有异常。例如,如果我修改上面的代码以出现错误(我想在控制台中看到的错误ReferenceError):

chrome.storage.local.get( 'foo', function() { a.b(); } );
不会

引发错误,因为 api 通过捕获和忽略所有错误来抑制它。在这种情况下如何调试我的代码?有没有办法恢复错误,或者所有这些 API 只是不打算与复杂的代码一起使用,我需要通过 console.log 手动调试以查找失败的内容?

更新 1

简单地将我自己的 try-catch 添加到所有回调中会增加代码的复杂性,这并不真正受欢迎。此外,简单的console.log比异常更糟糕,因为异常被开发工具捕获,以红色显示,附加堆栈跟踪等。当然,所有这些都可以用console.log来模拟,但这会增加更多的复杂性。

更新 2

似乎 js 代码忽略错误是一种 ommon实践,所以我被迫通过添加下划线插件并使用它来包裹每个回调来实现丑陋的解决方案:

function _safeblock( block )
{
  console.assert( block );
  return function() {
    try {
      block.apply( this, arguments );
    }
    catch( e ) {
      console.log( e.message, e.stack );
    }
  };
}

function _safecall( block )
{
  console.assert( block );
  _safeblock( block )();
}

_.mixin({
  safeblock: _safeblock,
  safecall: _safecall,
});

您可以尝试自己捕获它们。

chrome.storage.local.get( 'foo', function() {
    try{
        a.b();
    }catch(e){
        console.log(e);
        //do whatever
    } 
});

可以通过重写storage.local.get或创建泛型函数包装器来自动执行此操作。

您还可以使用 setTimeout 手动延迟函数,这将使库无法(在浏览器中)抑制您的错误

chrome.storage.local.get( 'foo', function() {
     setTimeout(function(){
           a.b();
     });
});

不过,这不会给你非常有意义的堆栈跟踪(函数之外的任何内容都不会显示),这使得它不太有用。如果您在性能敏感的情况下使用它,它也可能是性能开销(并且在浏览器中 setTimeout 至少需要几毫秒,不过有一个 postMessage 黑客)。

你可以简单地执行一个try-catch并使用console.error(适用于Firebug和Chrome DevTools,不确定其他

):
chrome.storage.local.get('foo', function () 
{   try { a.b(); }
    catch (e) { console.error(e.name + ": " + e.message); }
});

如果你不需要回调的参数,你可以创建一个包装函数:

function wrapTryCatch(func)
{   return function ()
    {   try { func.apply(this, arguments); }
        catch (e)
        {   var err = e.name + ': ' + e.message;
            console.error ? console.error(err)
            : console.log ? console.log(err)
            : alert(err);
        }
    }
}