Resource Loading onload and onerror
JavaScript Resource Loading: onload and onerror
The browser helps to track the loading of external resources, such as pictures, scripts and more. (浏览器有助于跟踪图片、脚本等外部资源的加载。)
Two primary events are used for that purpose:
onload: it supposes a successful load.
onerror: it means that an error has occurred.
Loading a Script
Loading a Script (加载脚本)
Imagine that you should load a third-party script and call a function residing there, as illustrated below:
let script = document.createElement('script');
script.src = "script.js";
document.head.append(script);
To run the function declared inside that script, you should wait until the script loads and only then call it. (要运行在该脚本中声明的函数,您应该等待脚本加载,然后再调用它。)
Please note, that here you could also use JavaScript modules, but they are not widely used by third-party libraries. (请注意,您也可以在此处使用JavaScript模块,但它们并未被第三方库广泛使用。)
Script.onload
The load event is the main helper here. It occurs once the was already loaded and executed. (加载事件是这里的主助手。一旦已经加载和执行,就会发生这种情况。)
Here is an example of the load event:
let script = document.createElement('script');
// any script can be loading from any domain
script.src = "https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.3.0/lodash.js"
document.head.append(script);
script.onload = function () {
// the script generates an auxiliary function
(//脚本生成一个辅助函数)
alert(_); // the function available
};
So, Script variables and run functions can be used in download. (因此,脚本变量和运行函数可用于下载。)
But, the loading may fail. Note that there isn’t any such script (error 404) or the server is done. (但是,加载可能会失败。请注意,没有任何此类脚本(错误404 )或服务器已完成。)
Let’s see what happens in such a circumstance. (让我们看看在这种情况下会发生什么。)
Script.onerror
Errors occurring during the script loading are tracked in an error event. (在脚本加载过程中发生的错误在错误事件中被跟踪。)
Let’s take a look at an example of requesting a non-existing script:
let script = document.createElement('script');
script.src = "https://example.com/404.js"; // no such script
document.head.append(script);
script.onerror = function () {
alert("Loading an error " + this.src); // Loading an error https://example.com/404.js
};
Please, take into account that the details of the HTTP error are not available here: you can’t know whether it’s an error 404, 500 or anything else.
Another important thing to note: the onload and onerror events track only the loading itself. In other words, errors occurring during the script processing and execution are out of the framework. So, if a script loaded efficiently, then onload happens, even if it includes some programming errors. For tracking the script errors, you can use a global handler called window.onerror.
Other Resources
Other Resources (其他资源)
The load and error events operate for any other resources that have an external src, like in the example below:
let img = document.createElement('img');
img.src = "https://www.w3cdoc.com/uploads/media/default/0001/05/9eb9e9cba721ba3bb5e653751449173197f2924a.png"; // (*)
img.onload = function () {
alert(`Image loaded, size ${img.width}x${img.height}`);
};
img.onerror = function () {
alert("An error occurred while loading image");
};
But, note that several resources begin loading once they are added to the document. The <img> is an exception to the rule. It begins to load after getting a src (*).
For <iframe>, the iframe.onload event occurs once the iframe loading is over. It is both for the efficient load and in case of an error.
Crossorigin policy
Crossorigin policy (Crossorigin政策)
Scripts from one site don’t have access to the scripts of the other one. For example, a script at https://www.instagram.com/ can’t read the user’s mailbox at https://gmail.com.
In other words, one origin (domain/port/protocol) can’t access the content of the other one. Even in case of having a subdomain, these are considered different origins. (换句话说,一个来源(域/端口/协议)无法访问另一个来源的内容。即使有子域名,这些也被认为是不同的来源。)
The rule above affects the resources from other domains, as well. An example of a script error.js consisting of a single (bad) function call is demonstrated below:
// error.js
noSuchFunction();
If you try loading it from the same site where it’s located, you will have this:
<script>
window.onerror = function(message, url, line, col, errorObj) {
alert(`${message}\n${url}, ${line}:${col}`);
};
</script>
<script src="/article/onload-onerror/crossorigin/error.js"></script>
A good error report can be seen here:
Uncaught ReferenceError: noSuchFunction is not defined https://javascript.info/article/onload-onerror/crossorigin/error.js, 1:1
The example of loading the same script from another domain will look like this:
<!DOCTYPE html>
<html>
<head>
<title>Title of the Document</title>
</head>
<body>
<script>
window.onerror = function(message, url, line, col, errorObj) {
alert(`${message}\n${url}, ${line}:${col}`);
};
</script>
<script src="https://cors.javascript.info/article/onload-onerror/crossorigin/error.js"></script>
</body>
</html>
So, there is a different report here:
Script error. , 0:0
There can be different details, depending on the browser. However, idea remains the same: any information regarding the internals of a script is hidden. The reason is that it is from a different domain.
Still, it is important to know details about errors. (尽管如此,了解有关错误的详细信息仍然很重要。)
There are services, listening for global errors using window.onerror, saving errors and providing an interface to access and analyze them. So, they make it possible to see real errors, triggered by the users. But, if a script has another origin, no more information will be available. (有服务,使用window.onerror监听全局错误,保存错误并提供访问和分析它们的接口。因此,它们可以查看用户触发的真实错误。但是,如果脚本具有其他来源,则将无法获得更多信息。)
For allowing cross-origin access, the <script> tag should have the crossorigin attribute. The remote server has to provide specific headers.
Three levels of cross-origin access exist:
No crossorigin attribute - the access is not allowed. For crossorigin=“anonymous” the access is allowed, in case the server responds with the header Access-Control-Allow-Origin including or the origin. Any authorization information or cookies are sent to the remote server. (无跨源属性-不允许访问。 对于crossorigin = “anonymous” ,如果服务器使用包含或源头的头Access-Control-Allow-Origin进行响应,则允许访问。 任何授权信息或Cookie都将发送到远程服务器。) crossorigin=“use-credentials”: the access is allowed in case the server sends back the Access-Control-Allow-Origin header with the origin and Access-Control-Allow-Credentials: true. Authorization information and cookies are sent to the remote server.
In case of not having any crossorigin attribute, the access will be prohibited. (如果没有任何跨源属性,则禁止访问。)
So, let’s see how to add it. (那么,让我们看看如何添加它。)
You can choose between “anonymous” and “use-credentials”.
In the event of not caring about the cookies, “anonymous” is the way to go, like this:
<!DOCTYPE html>
<html>
<head>
<title>Title of the Document</title>
</head>
<body>
<script>
window.onerror = function(message, url, line, col, errorObj) {
alert(`${message}\n${url}, ${line}:${col}`);
};
</script>
<script crossorigin="anonymous" src="https://cors.javascript.info/article/onload-onerror/crossorigin/error.js"></script>
</body>
</html>
Supposing that the server provides Access-Control-Allow-Origin header, the full error report is ready. (假设服务器提供Access-Control-Allow-Origin标头,则完整的错误报告就绪。)
Summary
Summary (概要)
Resources such as scripts, styles, images provide load and error events for tracking their loading:
The load event happens on a successful load. (-加载事件在成功加载时发生。)
The error event occurs on a failed load. (-加载失败时发生错误事件。)
, there is an exception: <iframe>, which only triggers the load, for each load completion, even if the page is not found. For resources, you can also use the readystatechange event. But it is used rarely as the load and error events are simpler and handier.