【问题标题】:Catch js errors when adding a script dynamically动态添加脚本时捕获 js 错误
【发布时间】:2013-12-30 10:53:46
【问题描述】:

为什么动态添加 javascript 代码时无法处理 js 错误?

代码如下:

try {
  var element = document.createElement("script");
  element.language = "javascript";
  element.type = "text/javascript";       
  element.defer = true;
  element.text = "this is not a javascript code";
  var head = document.getElementsByTagName('head')[0];
  head.appendChild(element);
} catch(err) {
  alert("error caught");
}

即使脚本不正确,也不会显示error caught 警报。

【问题讨论】:

  • 这是什么类型的错误,在普通的脚本标签中尝试不会抛出错误吗?无论如何,该代码(假设这只是一个示例)会引发 SyntaxError,这是一个无法通过 try-catch 语句处理的早期错误。

标签: javascript error-handling


【解决方案1】:

catch 语句应该在不同级别的代码中尝试在添加的代码中捕获错误,错误应该是异常而不是语法错误

<html>
<head>
<script type="text/javascript">
try {
    var element = document.createElement("script");
    element.language = "javascript";
    element.type = "text/javascript";       
    element.defer = true;
    element.text = "try{callingAnonymousMethod();} catch(ex) {alert('error caught');}";
    var head = document.getElementsByTagName('head')[0];
    head.appendChild(element);
} catch(err) {
  alert("error caught");
}
</script></head>
<body>

</body>
<html>

【讨论】:

  • 谢谢!这是一个有趣的想法。
【解决方案2】:

据我所知,没有办法处理某些脚本标签上的错误(甚至是语法错误)。 您可以使用window.onerror 并在错误消息的开头查找SyntaxError。我想,这就是你想要捕捉的错误。

【讨论】:

【解决方案3】:

用于从动态添加的脚本中捕获 src 加载错误

var element = document.createElement("script");
element.type = "text/javascript";
element.defer = true;
element.src = "Your link";

element.onerror = (error) => {
  alert("Error") ; //you will get to know some errors here
}

var windowErrorHandler = (event) =>{
    event.preventDefault(); //if you do not want to output SyntaxErrors to console
    var error = event.error;
    //and some errors here                      
};    
window.addEventListener('error', windowErrorHandler);

var head = document.getElementsByTagName('head')[0];
head.appendChild(element);

这是另一个动态导入 ES6 模块的示例 sn-p,您可能希望根据自己的需要进行调整:

 convertScriptToTree(){

        this.clearViews();
        

        window.scriptLoadedHook = ()=>{
                window.scriptLoadedHook = undefined;
                if(window.createModel){
                    this.model = window.createModel();
                }               
                this.refresh();             
        }; 

        var self = this;
                    
        this.editor.processText(async (sourceCode)=>{

            await new Promise((resolve, reject)=>{               

                var script = document.createElement('script');
                script.type = 'module';
                script.innerHTML = sourceCode + '\n' + 
                                   'if(window.scriptLoadedHook){window.scriptLoadedHook();}'; 

                var windowErrorHandler = (event) =>{
                    event.preventDefault();
                    var error = event.error;
                    error.stack = error.stack + '\n\n' + sourceCode;                    
                    window.removeEventListener('error', windowErrorHandler);
                    reject(error);
                };

                window.addEventListener('error', windowErrorHandler);  

                var rejectHandler = (event) =>{
                    console.log(event);
                    window.removeEventListener('error', windowErrorHandler);
                    var message = 'Please check the import statements:\n'+sourceCode;
                    reject(message);                        
                };              

                script.addEventListener('error', rejectHandler);                

                script.addEventListener('abort', rejectHandler);            
                             

                var loadedHandler = ()=>{
                    window.removeEventListener('error', windowErrorHandler);
                    resolve();
                };

                script.addEventListener('load', loadedHandler);
                script.onload = loadedHandler;

                var body = document.getElementsByTagName('body')[0];
                try {
                    body.appendChild(script); 
                } catch(error){
                    reject(error);
                }               

            })
            .catch(error => {
                console.warn('[Treez]: Could not process JavaScript code:\n', error);
            })
            .then(()=>{
                self.refreshViews();
            });                 
            
        });        
            
    }

【讨论】:

  • 这是非常错误的,你试过running your code吗?
  • @YellowAfterlife,请在Stackblitz 看看这个。可以在error event 中跟踪脚本加载期间发生的错误。请Check this了解更多详情。
  • 这个问题(和公认的答案)是关于捕捉语法错误的。 onerror 只会捕获 HTTP 错误。
  • 感谢 cmets。我改进了答案。
猜你喜欢
  • 1970-01-01
  • 2018-10-01
  • 2023-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-29
  • 2017-03-30
  • 2010-12-27
相关资源
最近更新 更多