我正在创建一个网页,其中嵌入了多个 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
命令(只执行最后一个)。有没有其他方法可以使其更具容错性?
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...
你可以用
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
函数用于计算没有局部作用域的函数。 请勿将其移除。有两种线路模式:
let
和 const
变量不会保存以供下一行代码使用。#!
前缀即可在单行上启用该模式。注意,我将您的
window.onload = …
更改为页面完成加载时触发的事件的正确语法。