Progress event

Types of progress events

Progress events are used to describe the progress of resource loading, mainly triggered by the loading of external resources such as AJAX requests, <img>, <audio>, <video>, <style>, <link> , Inherits the ProgressEvent interface. It mainly contains the following events.

-abort: Triggered when the external resource is aborted (such as the user canceled). If an error occurs that causes an abort, the event will not be triggered. -error: Triggered when external resources cannot be loaded due to an error. -load: Triggered when external resources are successfully loaded. -loadstart: Triggered when the external resource starts to load. -loadend: Triggered when external resources stop loading, the order of occurrence is after events such as error, abort, and load. -progress: Triggered continuously during the loading process of external resources. -timeout: Triggered when loading timeout.

Note that in addition to resource downloads, these events also exist for file uploads.

Below is an example.

image.addEventListener("load", function (event) {
  image.classList.add("finished");
});

image.addEventListener("error", function (event) {
  image.style.display = "none";
});

The above code adds a class of finished to the image element after the image element is loaded. If the loading fails, set the style of the image element to not display.

Sometimes, the image loading will be completed before the script runs, especially when the script is placed at the bottom of the web page, so it is possible that the listener functions of the load and error events will not be executed at all. Therefore, a more reliable way is to use the complete attribute to first determine whether the loading is complete.

function loaded() {
  // ...
}

if (image.complete) {
  loaded();
} else {
  image.addEventListener("load", loaded);
}

Since the element node of the DOM does not provide the attribute of whether to load the error or not, the listener function of the error event is best placed in the HTML code of the <img> element, so as to ensure that it will be executed 100% when a loading error occurs.

<img src="/wrong/url" onerror="this.style.display='none';" />

The listener function of the loadend event can be used to replace the listener function of the abort event, load event, and error event, because it always occurs after these events.

req.addEventListener("loadend", loadEnd, false);

function loadEnd(e) {
  console.log("End of transmission, unknown success or failure");
}

The loadend event itself does not provide the reason for the end of the progress, but it can be used to do some operations that need to be done in all loading end scenes.

In addition, the error event has a special property, that is, it does not bubble. Therefore, the error event of the child element will not trigger the error event listener function of the parent element.

ProgressEvent interface

The ProgressEvent interface is mainly used to describe the progress of external resource loading, such as AJAX loading, <img>, <video>, <style>, <link> and other external resource loading. All progress-related events inherit this interface.

The browser natively provides the ProgressEvent() constructor to generate event instances.

new ProgressEvent(type, options);

The ProgressEvent() constructor accepts two parameters. The first parameter is a string, indicating the type of event, this parameter is required. The second parameter is a configuration object, which represents the attributes of the event. This parameter is optional. In addition to the configuration properties of the Event interface, the configuration object can also use the following properties, all of which are optional.

-lengthComputable: Boolean value, indicating whether the total load can be calculated, the default is false. -loaded: Integer, which means the amount that has been loaded, the default is 0. -total: Integer, indicating the total amount to be loaded, the default is 0.

ProgressEvent has corresponding instance attributes.

-ProgressEvent.lengthComputable -ProgressEvent.loaded -ProgressEvent.total

If ProgressEvent.lengthComputable is false, ProgressEvent.total is actually meaningless.

Below is an example.

var p = new ProgressEvent("load", {
  lengthComputable: true,
  loaded: 30,
  total: 100,
});

document.body.addEventListener("load", function (e) {
  console.log("Already loaded:" + (e.loaded / e.total) * 100 + "%");
});

document.body.dispatchEvent(p);
// Already loaded: 30%

The above code first constructs a load event, which is caught by the listener function after being thrown.

The following is a practical example.

var xhr = new XMLHttpRequest();

xhr.addEventListener("progress", updateProgress, false);
xhr.addEventListener("load", transferComplete, false);
xhr.addEventListener("error", transferFailed, false);
xhr.addEventListener("abort", transferCanceled, false);

xhr.open();

function updateProgress(e) {
  if (e.lengthComputable) {
    var percentComplete = e.loaded / e.total;
  } else {
    console.log("Cannot calculate progress");
  }
}

function transferComplete(e) {
  console.log("End of transmission");
}

function transferFailed(evt) {
  console.log("An error occurred during transmission");
}

function transferCanceled(evt) {
  console.log("User cancelled the transmission");
}

The above is the progress event of the download process, and there are also progress events of the upload process. At this time, all listening functions must be placed on the XMLHttpRequest.upload object.

var xhr = new XMLHttpRequest();

xhr.upload.addEventListener("progress", updateProgress, false);
xhr.upload.addEventListener("load", transferComplete, false);
xhr.upload.addEventListener("error", transferFailed, false);
xhr.upload.addEventListener("abort", transferCanceled, false);

xhr.open();