18

我想将错误传递给警报,以警告用户他们在代码中犯了错误,即使他们没有打开控制台。

    var doc=(frame.contentWindow.document || obj.contentDocument|| obj.contentWindow);
    var head = doc.getElementsByTagName('head')[0];
    var scriptElement = doc.createElement('script');
    scriptElement.setAttribute('type', 'text/javascript');
    scriptElement.text = scripts;

    try{
        head.appendChild(scriptElement);
    }
     catch(e){ alert("error:"+e.message +"  linenumber:"+e.lineNumber);}

当脚本包含错误时,appendChild 会引发错误。它直接进入控制台,我希望它显示在警报中,因为它是为孩子们准备的,他们可能不会检查控制台。try catch 块不会捕获错误。我用 eval(scripts) 试过了。

   try{
   eval(scripts);} catch(e){ alert("error:"+e.message +"  linenumber:"+e.lineNumber);}

这确实有效,但这意味着代码被执行了两次,这在某些情况下非常不方便。

我试过猴子修补console.error:

       console.log=function(){alert("taking over the log");}
       console.error=function(){alert("taking over the log");}

但这仅在我真正使用console.error时才有效。不是在抛出实际错误时。如果不是console.error,在真正错误的情况下,什么函数将错误发送到控制台?我可以访问并更改它吗?有任何想法吗?帮助将不胜感激。谢谢珍妮塔

4

3 回答 3

25

虽然try ... catch将处理脚本最初运行的代码,但正如 Jenita 所说,它不会捕获语法错误,也不会捕获稍后执行的回调函数引发的错误(在 try-catch 完成很久之后)。这意味着传递给setTimeoutor的任何函数都没有错误addEventListener

但是,您可以尝试不同的方法。在窗口上注册一个错误监听器。

window.addEventListener("error", handleError, true);

function handleError(evt) {
    if (evt.message) { // Chrome sometimes provides this
      alert("error: "+evt.message +" at linenumber: "+evt.lineno+" of file: "+evt.filename);
    } else {
      alert("error: "+evt.type+" from element: "+(evt.srcElement || evt.target));
    }
}

这将在回调函数抛出异常时调用。但它也会触发一般的 DOM 错误,例如图像无法加载,您可能对此不感兴趣。

它也应该在语法错误时触发,但前提是它能够首先运行,所以你应该把它放在一个单独的脚本中,而不是可能包含拼写错误的脚本!(稍后脚本中的语法错误将阻止同一脚本顶部的有效行运行。)

不幸的是,我从来没有找到从evtFirefox 中获取行号的方法。 (编辑:四处看看,我想它现在可能就在那里。)


我在尝试编写FastJSLogger时发现了这一点,这是我在浏览器开发工具有点慢时使用的页内记录器。

不顾一切地捕捉行号,我开始尝试包装器setTimeoutaddEventListener这将重新引入围绕这些调用的 try-catch。例如:

var realAddEventListener = HTMLElement.prototype.addEventListener;

HTMLElement.prototype.addEventListener = function(type,handler,capture,other){
    var newHandler = function(evt) {
        try {
            return handler.apply(this,arguments);
        } catch (e) {
            alert("error handling "+type+" event:"+e.message +"  linenumber:"+e.lineNumber);
        }
    };

    realAddEventListener.call(this,type,newHandler,capture,other);
};

显然,这应该在注册任何事件监听器之前完成,甚至可能在加载像 jQuery 这样的库之前完成,以防止它们addEventListener在我们能够替换它之前获取对真实的引用。

于 2013-11-28T02:40:01.823 回答
3

好的,因此不太优雅但高效的方法是“重构”您的先天控制台功能。基本上,您收到的任何错误或警告都由一个与熟悉的 console.log() 函数非常相似的 javascript 函数输出。我所说的函数是console.warn()、console.info() 和console.error()。现在让我们“重新映射”每个人的工作:

//remap console to some other output
var console = (function(oldCons){
    return {
        log: function(text){
            oldCons.log(text);
            //custom code here to be using the 'text' variable
            //for example: var content = text;
            //document.getElementById(id).innerHTML = content
        },
        info: function (text) {
            oldCons.info(text);
            //custom code here to be using the 'text' variable
        },
        warn: function (text) {
            oldCons.warn(text);
            //custom code here to be using the 'text' variable
        },
        error: function (text) {
            oldCons.error(text);
           //custom code here to be using the 'text' variable
        }
    };
}(window.console));

//Then redefine the old console
window.console = console;

现在,通常我强烈建议不要在生产中使用这样的东西并将其限制为调试目的,但是由于您正在尝试开发一个显示控制台输出的功能,所以那里的线条很模糊,所以我会留下它由你决定。

于 2017-10-02T15:59:02.337 回答
1

您可以将脚本包装在自己的 try/catch 中,例如:

var doc=(frame.contentWindow.document || obj.contentDocument|| obj.contentWindow);
var head = doc.getElementsByTagName('head')[0];
var scriptElement = doc.createElement('script');
scriptElement.setAttribute('type', 'text/javascript');
scriptElement.text = "try{"+scripts+"}catch(e){console.error(e);alert('Found this error: ' + e +'. Check the console.')}"
head.appendChild(scriptElement);
于 2013-11-27T21:55:31.953 回答