将脚本标记插入DOM时捕获SyntaxError异常

时间:2014-05-14 11:00:38

标签: javascript exception dom syntax-error

在单页面Web应用程序中,有时需要将新的javascript块附加到页面上。

假设我们有以下脚本标记内容,它们有语法错误,例如缺少引号。它必须是一个错误,它在分析时引发异常而不是运行时。

var test = {"foo":1, "bar":"test, "baz":"foobar"};

现在,您创建一个新的脚本元素,将文本注入内部并将其附加到DOM:

var text = 'var test = {"foo":1, "bar":"test, "baz":"foobar"};';        
var node = document.createElement('script');
node.appendChild(document.createTextNode(text));
head.appendChild(node);

当然,在最后一行,抛出了“SyntaxError”异常。

问题是将最后一行放在try catch块中不起作用,异常永远不会被捕获。我设法使用旧的脏window.onerror事件捕获错误,但只在Chrome上。例如,在IE11上,如果禁用了脚本错误,则只能在控制台打开的情况下使用。

所以问题是,如何可靠地捕获此异常以便能够向用户显示消息?

由于

2 个答案:

答案 0 :(得分:0)

不确定是否有办法捕获它,但如果您可以控制加载的脚本,您当然可以使用以下解决方法知道何时发生错误。

问题是SyntaxError没有通过" onerror",而是用" onload"完成。 所以hack是在源脚本的末尾插入一个小的标志/赋值语句,并在" onload"回调,除了使用" onerror"。

捕获其他错误

答案 1 :(得分:0)

为了捕获SyntaxError,可以使用window.addEventListener('error', ...)方法并阻止默认设置。一些示例代码:

var 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 = (error) =>{
                window.removeEventListener('error', windowErrorHandler);
                reject(error);                  
            };              

            script.addEventListener('error', rejectHandler);
            //script.onerror = rejectHandler;

            script.addEventListener('abort', rejectHandler);
            //script.onabort = 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('Could not process JavaScript code:\n', error);
        })
        .then(()=>{
            //refresh app etc.;
        });                 
        
    });