浏览器允许跟踪外部资源的加载 —— 脚本、iframes、图像等。

有两个事件

  • onload —— 成功加载,
  • onerror —— 发生异常。

加载脚本

假设我们需要调用属于外部脚本的函数。

我们可以像这样动态加载:

let script = document.createElement('script');
script.src = "my.js";

document.head.append(script);

…但如何运行声明在脚本中的函数?我们需要等到脚本被加载后才能调用它。

script.onload

主要得力于 load 事件。它在脚本被加载和执行后才被触发。

例如:

let script = document.createElement('script');

// 可以从任意域名加载脚本
script.src = "https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.3.0/lodash.js"
document.head.append(script);

script.onload = function() {
  // 脚本创建了一个辅助函数 "_"
  alert(_); // 函数可用
};

因此,在 onload 中我们使用脚本变量、运行函数等。

…如果加载失败怎么办?比如,没有这样的脚本(错误 404)或者服务器宕机(不可用)。

script.onerror

发生在脚本(不是执行)期间的错误可以在 error 事件上进行追踪。

比如,我们请求一个不存在的脚本:

let script = document.createElement('script');
script.src = "https://example.com/404.js"; // 没有这样的脚本
document.head.append(script);

script.onerror = function() {
  alert("Error loading " + this.src); // 加载 https://example.com/404.js 发生错误
};

请注意,我们无法再这获取错误的更多细节。我们不知道错误是 404 还是 500 或者其他情况,只知道是加载失败了。

其他资源

loaderror 事件也适用于其他资源。但是也存在细微的差别。

例如:

<img><link>(外部样式表)
loaderror 事件都如期运行。
<iframe>
只有当 iframe 加载完成时会发生 load 事件。在成功或失败的情况下,都会触发它。这是历史原因。

总结

<img> 图像、外部样式表、脚本和其他资源都提供了 loaderror 事件来追踪它们的加载:

  • load 在成功加载时被触发。
  • error 在加载失败时被触发。

只有 <iframe> 特殊:出于历史原因,即使页面没有被找到,它总会触发 load 来完成任何加载。

readystatechange 事件也适用于资源,但很少被使用,因为 load/error 事件更简单。

任务

重要程度: 4

通常,图像在被创建时就会被加载,因此当我们在页面中添加 <img> 时,用户不会立即看到图像。浏览器首先会加载它。

我们可以像这样“提前”创建来立即显示图像:

let img = document.createElement('img');
img.src = 'my.jpg';

浏览器开始加载图像然后保存在缓存中。之后,当相同图像出现在文档中时(无论怎样),它会立即显示。

创建一个从 source 数组中加载所有图像,并在准备就绪时运行 callbackpreloadImages(sources, callback) 函数。

例如,这将在加载图像之后显示一个 alert

function loaded() {
  alert("Images loaded")
}

preloadImages(["1.jpg", "2.jpg", "3.jpg"], loaded);

如果出现错误,函数仍会认为图像已经“被加载”。

换句话说,当所有图像被加载或出现错误输出时,callback 就会被执行。

比如,当我们计划显示一个包含许多可滚动图像的图库,并希望确保所有的图像都被加载时,这个函数是非常有用的。

在源文档中,你可以找到指向测试图像的链接,以及检查它们是否已被加载的代码。它应该输出 300

打开一个任务沙箱。

算法:

  1. 为每个资源制作 img
  2. 为每个 image 添加 onload/onerror
  3. onloadonerror 被触发时计数器加 1。
  4. 当计数器值等于资源值时 —— 结束:callback()

使用沙箱打开解决方案。

教程路线图

评论

在评论之前先阅读本内容…
  • 欢迎你在文章下添加补充内容、提出你的问题或回答提出的问题。
  • 使用 <code> 标签插入几行代码,对于多行代码 — 可以使用 <pre>,对于超过十行的代码 — 建议使用沙箱(plnkrJSBincodepen 等)。
  • 如果你无法理解文章中的内容 — 请详细说明。