XMLHttpRequest is a browser interface that enables Javascript to perform HTTP(S) communication.
At first, Microsoft introduced this interface in IE 5. Because it is so useful, other browsers have imitated and deployed, so ajax operations were born.
However, this interface has not been standardized, and the implementation of each browser is more or less different. After the concept of HTML 5 was formed, W3C began to consider standardizing this interface. In February 2008, the XMLHttpRequest Level 2 draft was proposed.
This new version of XMLHttpRequest proposes many useful new features that will greatly promote Internet innovation. This article introduces this new version in detail.
1. Old version of XMLHttpRequest object
Before introducing the new version, let’s review the usage of the old version.
First, create a new instance of XMLHttpRequest.
var xhr = new XMLHttpRequest();
Then, an HTTP request is issued to the remote host.
The code copy is as follows:
xhr.open('GET', 'example.php');
xhr.send();
Then, wait for the remote host to respond. At this time, you need to monitor the status changes of the XMLHttpRequest object and specify the callback function.
xhr.onreadystatechange = function(){ if ( xhr.readyState == 4 && xhr.status == 200 ) { alert( xhr.responseText ); } else { alert( xhr.statusText ); }};The above code contains the main properties of the old version of XMLHttpRequest object:
The code copy is as follows:
* xhr.readyState: The status of the XMLHttpRequest object, equal to 4 means that the data has been received.
* xhr.status: The status code returned by the server, equal to 200 means everything is normal.
* xhr.responseText: Text data returned by the server
* xhr.responseXML: XML format data returned by the server
* xhr.statusText: The status text returned by the server.
2. Disadvantages of the old version
The old version of XMLHttpRequest object has the following disadvantages:
* Only text data transmission is supported and cannot be used to read and upload binary files.
* When transmitting and receiving data, there is no progress information, so you can only prompt whether it has been completed.
* Due to "Same Origin Policy", you can only request data from servers with the same domain name.
3. Functions of the new version
The new version of the XMLHttpRequest object has made significant improvements to the shortcomings of the old version.
The code copy is as follows:
* You can set the time limit for HTTP requests.
* FormData objects can be used to manage form data.
* Files can be uploaded.
* You can request data under different domain names (cross-domain request).
* You can get binary data on the server side.
* You can obtain the progress information of data transmission.
Next, I will introduce these new features one by one.
4. Time limit for HTTP requests
Sometimes, ajax operations are time-consuming and it is impossible to predict how much time it will take. If the internet speed is very slow, users may have to wait for a long time.
The new version of XMLHttpRequest object has added a timeout attribute, which can set the time limit for HTTP requests.
xhr.timeout = 3000;
The above statement sets the maximum waiting time to 3000 milliseconds. After this time limit is passed, the HTTP request will be automatically stopped. There is also a timeout event that specifies the callback function.
The code copy is as follows:
xhr.ontimeout = function(event){
alert('Request timeout!');
}
Currently, Opera, Firefox, and IE 10 support this property. This property of IE 8 and IE 9 belongs to the XDomainRequest object, while Chrome and Safari do not support it.
5. FormData object
Ajax operations are often used to pass form data. To facilitate form processing, HTML 5 has added a FormData object to mock forms.
First, create a new FormData object.
var formData = new FormData();
Then, add a form item to it.
formData.append('username', 'Zhang San');
formData.append('id', 123456);
Finally, directly transmit this FormData object. This is exactly the same as submitting a web form.
xhr.send(formData);
The FormData object can also be used to get the value of a web form.
The code copy is as follows:
var form = document.getElementById('myform');
var formData = new FormData(form);
formData.append('secret', '123456'); // Add a form item
xhr.open('POST', form.action);
xhr.send(formData);
6. Upload files
The new version of XMLHttpRequest object can not only send text information, but also upload files.
Assuming files are a form element (input[type="file"]) of "select file", we load it into the FormData object.
The code copy is as follows:
var formData = new FormData();
for (var i = 0; i < files.length;i++) {
formData.append('files[]', files[i]);
}
Then, send this FormData object.
xhr.send(formData);
7. Cross-domain resource sharing (CORS)
The new version of XMLHttpRequest object can issue HTTP requests to servers with different domain names. This is called "Cross-origin resource sharing" (CORS).
The prerequisite for using "cross-domain resource sharing" is that the browser must support this function, and the server must agree to this "cross-domain". If the above conditions can be met, the code is written exactly the same as that of non-cross-domain requests.
xhr.open('GET', 'http://other.server/and/path/to/script');
Currently, in addition to IE 8 and IE 9, mainstream browsers support CORS, and IE 10 will also support this function. For server-side settings, please refer to "Server-Side Access Control".
8. Receive binary data (Method A: Rewrite MIMEType)
The old version of XMLHttpRequest object can only retrieve text data from the server (otherwise its name will not start with XML), while the new version can retrieve binary data.
Here are two different ways. The older approach is to override the MIMEType of the data, disguise the binary data returned by the server as text data, and tell the browser that this is a user-defined character set.
xhr.overrideMimeType("text/plain; charset=x-user-defined");
Then, use the responseText property to receive the binary data returned by the server.
var binStr = xhr.responseText;
Since the browser treats it as text data at this time, it must be restored to binary data one by one.
The code copy is as follows:
for (var i = 0, len = binStr.length; i < len; ++i) {
var c = binStr.charCodeAt(i);
var byte = c & 0xff;
}
The bit operation "c & 0xff" of the last line means that among the two bytes of each character, only the next byte is retained and the previous byte is thrown away. The reason is that when the browser interprets characters, it will automatically interpret the characters into Unicode's 0xF700-0xF7ff section.
8. Receive binary data (Method B: responseType property)
The newer way to retrieve binary data from the server is to use the newly added responseType property. If the server returns text data, the value of this property is "TEXT", which is the default value. Newer browsers also support other values, that is, they can receive data in other formats.
You can set the responseType to blob, which means that the server is sending back a binary object.
The code copy is as follows:
var xhr = new XMLHttpRequest();
xhr.open('GET', '/path/to/image.png');
xhr.responseType = 'blob';
When receiving data, just use the Blob object that comes with your browser.
var blob = new Blob([xhr.response], {type: 'image/png'});
Note that it is to read xhr.response, not xhr.responseText.
You can also set the responseType to arraybuffer and install the binary data in an array.
The code copy is as follows:
var xhr = new XMLHttpRequest();
xhr.open('GET', '/path/to/image.png');
xhr.responseType = "arraybuffer";
When receiving data, you need to traverse this array.
The code copy is as follows:
var arrayBuffer = xhr.response;
if (arrayBuffer) {
var byteArray = new Uint8Array(arrayBuffer);
for (var i = 0; i < byteArray.byteLength; i++) {
// do something
}
}
For a more detailed discussion, see Sending and Receiving Binary Data.
9. Progress information
The new version of XMLHttpRequest object has a progress event when transmitting data, which is used to return progress information.
It is divided into two situations: upload and download. The downloaded progress event belongs to the XMLHttpRequest object, and the uploaded progress event belongs to the XMLHttpRequest.upload object.
Let's first define the callback function of the progress event.
The code copy is as follows:
xhr.onprogress = updateProgress;
xhr.upload.onprogress = updateProgress;
Then, in the callback function, use some properties of this event.
The code copy is as follows:
function updateProgress(event) {
if (event.lengthComputable) {
var percentComplete = event.loaded / event.total;
}
}
In the above code, event.total is the total bytes that need to be transferred, and event.loaded is the bytes that have been transferred. If event.lengthComputable is not true, event.total is equal to 0.
There are five other events related to the progress event, which can specify the callback function separately:
* load event: The transfer completed successfully.
* abort event: The transmission was cancelled by the user.
* error event: An error occurred during transmission.
* loadstart event: The transfer starts.
* loadEnd event: The transmission ends, but I don’t know whether it succeeds or fails.
10. Reading materials
1. Introduction to XMLHttpRequest Level 2: A comprehensive introduction to new features.
2. New Tricks in XMLHttpRequest 2: Some usage introductions.
3. Using XMLHttpRequest: Some advanced usages, mainly targeting Firefox browsers.
4. HTTP Access Control: CORS Overview.
5. DOM access control using cross-origin resource sharing: 9 types of HTTP header information of CORS
6. Server-Side Access Control: Server-side CORS settings.
7. Enable CORS: Server CORS settings.