`window.onload`可以容错吗?有更好的选择吗?

问题描述 投票:0回答:2

我正在创建一个网页,其中嵌入了多个 GeoGebra 文件。这意味着对于每个 GeoGebra 小程序,我在

<div>
中都有一个
<body>
元素,并带有关联的脚本来配置它;在
<body>
的末尾,我有以下脚本,将所有小程序添加到其关联的
<div>
中:

<script>
    window.onload = function() {
        applet_0.inject('ggb-element-0');
        applet_1.inject('ggb-element-1');
        applet_2_NoLimit.inject('ggb-element-2-NoLimit');
        applet_2_YesLimit.inject('ggb-element-2-YesLimit');
        applet_3.inject('ggb-element-3');
        applet_4_Flat.inject('ggb-element-4-Flat');
        applet_4_Faster.inject('ggb-element-4-Faster');
    };
</script>

我注意到,如果脚本的前六行中的任何一行失败,例如,如果无法加载关联的文件,则失败行后面的所有行都不会执行。

即使其中一个嵌入出现问题,我也想让这项工作正常进行。我已经发现我不能有多个

window.onload
命令(只执行最后一个)。有没有其他方法可以使其更具容错性?

javascript onload
2个回答
2
投票

您可以通过调用

window.addEventListener
而不是设置
window.onload
来拥有多个加载事件侦听器。通过这种方式添加的监听器会按照添加的顺序执行。通过提供
{once: true}
作为第三个参数,事件侦听器将在调用后自动删除。在您认为合适的加载事件被触发之前,可以将侦听器添加到代码中的任何位置。

例如,前两个侦听器可以通过以下方式添加

addEventListener('load', ()=> applet_0.inject('ggb-element-0'), {once: true});

 //...

addEventListener('load', ()=> applet_2_NoLimit.inject('ggb-element-2-NoLimit'), {once: true});

// etc...

1
投票

你可以用

try {} catch {}
语句包裹每一行,但这需要大量的复制粘贴,而且代码会非常混乱。但是,如果您创建一个辅助函数,则可以在不使代码不可读的情况下实现:

function evalFunction(scopeCode) {
  return new Function(scopeCode);
}

function runThroughErrors(code) {
  if(typeof code != "string") throw TypeError("Parameter 'code' is not a string");
  let lines = code.split(/\r\n|\r|\n/g),
    func = "";

  for(let line of lines) {
    let pat = /^#!/,
      lnCode = line.replace(pat, "");
    func += pat.test(line)?
    lnCode+"\n"
    :`try {
      ${lnCode}
    } catch(err) {
      // Do something with the error.
      // This will be run with each ignored error.
    }`
  }
  return evalFunc(func);
}


document.body.addEventListener("load", runThroughErrors(`
  applet_0.inject('ggb-element-0');
  applet_1.inject('ggb-element-1');
  applet_2_NoLimit.inject('ggb-element-2-NoLimit');
  applet_2_YesLimit.inject('ggb-element-2-YesLimit');
  applet_3.inject('ggb-element-3');
  applet_4_Flat.inject('ggb-element-4-Flat');
  applet_4_Faster.inject('ggb-element-4-Faster');
`));

用法是将 JavaScript 代码以字符串格式作为参数传递给

runThroughErrors
函数。该函数返回一个包含您的代码的 JS 函数,但错误将被忽略。

重要(使用
runThroughErrors

  • 错误捕获断点位于行的每一端(如果是默认模式行)。
  • 在每个语句后面添加行尾,不支持多行语句。
  • evalFunction
    函数用于计算没有局部作用域的函数。 请勿将其移除。

有两种线路模式:

  • default - 捕获该行的错误,但
    let
    const
    变量不会保存以供下一行代码使用。
  • 不捕获 - 该行的错误不会被捕获,但所有变量都会被保存以在下一行代码中使用。通过在该行前添加
    #!
    前缀即可在单行上启用该模式。

注意,我将您的

window.onload = …
更改为页面完成加载时触发的事件的正确语法。

© www.soinside.com 2019 - 2024. All rights reserved.