The development history of XMLHttpRequest
At the heart of Ajax technology is the XMLHttpRequest object. We use an XMLHttpRequest object to send an Ajax request. This feature was first introduced by Microsoft, and other browser vendors have since provided the same implementation.
XMLHttpRequest has been so widely accepted that it has been standardized by the W3C and put forward the XMLHttpRequest standard. The XMLHttpRequest standard is divided into Level 1 and Level 2.
Not all browsers fully implement the XMLHttpRequest Level 2 specification, but all browsers implement some of its requirements.
XMLHttpRequest Level 1 has the following disadvantages:
- Cannot send binary files (such as pictures, video, audio, etc.), can only send plain text data.
- In the process of sending and obtaining data, you cannot obtain real-time progress information, but can only judge whether the data is completed.
- Cross-domain requests cannot be sent because of the same origin policy.
Level 2 Is an improvement on Level 1. The following functions are added to XMLHttpRequest Level 2:
- Cross-domain requests can be sent if the server allows it.
- Supports sending and receiving binary data.
- new
formData
Object that supports sending form data. - You can obtain progress information when sending and retrieving data.
- You can set the timeout period for the request.
The following line of code creates the XMLHttpRequest object.
const xhr = new XMLHttpRequest()
Copy the code
Compatibility query: caniuse.com/#search=XML…
XMLHttpRequest object sends request related API
Request header correlation
Accept
: Type of content that the client can process. Such as:Accept: */*
.Accept-Charset
: Type of character set that the client can handle. Such as:Accept-Charset: utf8
.Accept-Encoding
: Compression encoding that the client can handle. Such as:Accept-Encoding: gzip, deflate, br
.Accept-Language
: Indicates the language currently set by the client. Such as:Accept-Language: zh-CN,zh; Q = 0.9, en. Q = 0.8
.Connection
: Indicates the type of connection between the client and the server. Such as:Connection: keep-alive
.Cookie
: Any of the current page SettingsCookie
.Host
: Domain where the request page is issued.Referer
: indicates the address of the source page of the currently requested page, that is, the current page is accessed through a link in this source page.User-Agent
: user agent character string of the client. Generally, information about the browser, browser kernel, and operating system is displayed.Content-Type
: The client tells the server what type of data is actually sent. Such as:Content-Type: application/x-www-form-urlencoded
.
More references: developer.mozilla.org/zh-CN/docs/…
Open () method
The open() method is used to initialize a request.
The open() method takes three arguments:
- The first parameter
method
: Type of request to send. Such asGET
,POST
,PUT
,DELETE
And so on. - Second parameter
url
: the requestURL
. - The third parameter
async
: Boolean value for whether to send requests asynchronously.true
Send requests asynchronously.
const xhr = new XMLHttpRequest()
xhr.open('get'.'/userInfo'.true)
Copy the code
Calling the open() method does not actually send the request, but just starts a request ready to be sent.
The send () method
The send() method is used to send HTTP requests.
The send() method takes one argument:
- The first parameter
data
: Data sent as the body of the request. If the data does not need to be sent through the request body, it must be passed innull
. This parameter can accept strings,FormData
,Blob
,ArrayBuffer
Such as type.
const xhr = new XMLHttpRequest()
xhr.send(null)
Copy the code
SetRequestHeader () method
The setRequestHeader() method sets custom request header information.
The setRequestHeader() method takes two arguments:
- The first parameter
header
: The name of the header field. - Second parameter
value
: The value of the header field.
To successfully send the request header information, this method must be called between open() and send().
const xhr = new XMLHttpRequest()
xhr.open('get'.'/server'.true)
xhr.setRequestHeader('MyHeader'.'MyValue')
xmlhttp.send()
Copy the code
ReadyState property and onReadyStatechange event
The readyState property represents the current active phase of the request/response process. The values of this attribute are as follows:
- 0 (
UNSENT
) is not initialized. Has not yet calledopen()
Methods. - 1 (
OPENED
Start). Already callopen()
Method, but not calledsend()
Methods. - 2 (
HEADERS_RECEIVED
Sent). Already callsend()
Method, but no response has been received. - 3 (
LOADING
Received). Partial response data has been received. - 4 (
DONE
Completed). All response data has been received.
An onReadyStatechange event is emitted whenever the value of the readyState property changes. Use this event to detect the value of readyState after each state change. Normally, only phases with readyState of 4 are processed, when all the data is ready.
const xhr = new XMLHttpRequest()
xhr.open('get'.'/server'.true)
xhr.onreadystatechange = function () {
if(xhr.readyState ! = = 4) {return
}
if(xhr.status >= 200 && xhr.status < 300) {
console.log(xhr.responseText)
}
}
xhr.send(null)
Copy the code
The timeout property and the onTimeout event
The timeout attribute indicates how many milliseconds the request has to wait for the response to terminate. If the browser has not received a response within the specified time, the onTimeout event handler is fired.
const xhr = new XMLHttpRequest()
xhr.open('get'.'/server'.trueXhr.ontimeout = 3000 // After the request times out, the request automatically terminates and the onTimeout event handler xhr.ontimeout = is calledfunction(){
console.log('Request timed out')
}
xhr.send(null)
Copy the code
OverrideMimeType () method
The overrideMimeType() method overrides the MIME type returned by the server to allow the browser to handle it differently.
If the data type returned by the server is TEXT/XML, and for some reason the browser fails to parse, the data will not be retrieved. To retrieve the raw data, we can change the MIME type to text/plain so that the browser doesn’t parse it automatically and we can retrieve the original text.
const xhr = new XMLHttpRequest()
xhr.open('get'.'/server'.true)
xhr.overrideMimeType('text/plain')
xhr.send(null)
Copy the code
ResponseType attribute
The responseType property is a string representing the type of data returned by the server. Use the xhr.response attribute to receive.
This property is writable and can be set after the open() method is called but before the send() method to tell the server to return the specified type of data. If responseType is set to an empty string, this is equivalent to the default text.
The responseType property can be set to the following format types:
responseType The value of the attribute |
response The data type of the property |
instructions |
---|---|---|
"" |
String string |
The default value is equal totext (In no settingresponseType When) |
"text" |
String string |
The server returns text data |
"document" |
Document object |
Hope to return toXML When formatting data |
"json" |
javaScript object |
IE10/IE11 Does not support |
"blob" |
Blob object |
The server returns binary objects |
"arrayBuffer" |
ArrayBuffer object |
The server returns a binary array |
When setting responseType to a specific type, you need to make sure that the type returned by the server is compatible with the type you set to return. So if the two types are incompatible, the data returned by the server will become NULL, even if the server returned data.
Setting responseType to a synchronous request raises an InvalidAccessError exception.
Const XHR = new XMLHttpRequest() xhr.open()'get'.'/server/image.png'.true)
xhr.responseType = 'blob'
xhr.onload = function(e) {
if (xhr.status >= 200 && xhr.status < 300) {
const blob = this.response
// ...
}
}
xhr.send(null)
Copy the code
WithCredentials attribute
The withCredentials attribute is a Boolean value that indicates whether credentials (such as cookies, HTTP authentication, and client SSL certificates) are coaccompanied with cross-domain requests. The default is false.
If you need to send cookies across domain Ajax requests, you need to set the withCredentials attribute to true. If xhr.withCredentials are configured in the same domain, the effect is the same regardless of whether you configure true or false.
const xhr = new XMLHttpRequest()
xhr.open('get'.'/server'.true)
xhr.withCredentials = true
xhr.send(null)
Copy the code
When the withCredentials are set to true, the response header access-Control-allow-origin must be added at the back end, and the domain name must be specified instead of *. Add the access-Control-allow-credentials header to true.
response.addHeader("Access-Control-Allow-Origin"."http://example.com")
response.addHeader("Access-Control-Allow-Credentials"."true")
Copy the code
Abort () method and onabort event
The abort() method is called to cancel the asynchronous request before the response is received. When a request is terminated, its readyState property is set to 0. After terminating the request, the XMLHttpRequeat object should also be dereferenced.
When abort() is called, the onabort event is fired.
const xhr = new XMLHttpRequest()
xhr.open('get'.'/server'.true)
xmlhttp.onabort = function () {
console.log('Request aborted'} xmlhttp.send() // Calls the onabort callback function xmlhttp.abort() that we defined above.Copy the code
A GET request
Appending the query string argument to the end of the URL sends the information to the server.
The encoding mode of GET parameters cannot be manually interfered, which leads to different encoding modes of different browsers. Therefore, the most reliable scheme is manual pre-encoding and manual decoding, thus forbidding the interference of browser encoding.
Const XHR = new XMLHttpRequest() // encodeURIComponent() const tempParam = encodeURIComponent()'age')
const tempValue = encodeURIComponent('20')
xhr.open('get'.'/server? tempParam=tempValue&money=100'.true)
Copy the code
A POST request
The POST request submits the data as the body of the request. Here are four common ways to submit data in a POST request.
application/x-www-form-urlencoded
A browser’s native
multipart/form-data
When a form uploads a file, the
application/json
When sending an Ajax request, use application/ JSON as the request header to tell the server that the body of the message is a serialized JSON string.
text/xml
Using HTTP as the transport protocol and XML as the encoded remote invocation specification.
Simulate form submission using XMLHttpRequest
Set the Content-Type header to Application/X-www-form-urlencoded. You can use the XMLHttpRequest object to mimic form submission.
const xhr = new XMLHttpRequest()
xhr.open('post'.'/server'.true)
xhr.setRequestHeader('Content-Type'.'application/x-www-form-urlencoded')
const form = document.getElementById('myForm') // serialize() for the form serialization method xhr.send(serialize(form))Copy the code
You can also serialize FormData using XMLHttpRequest level 2 FormData.
const xhr = new XMLHttpRequest()
xhr.open('post'.'/server'.true)
const form = document.getElementById('myForm')
const formData = new FormData(form)
formData.append("id"."123456")
xhr.send(formData)
Copy the code
Using FormData you don’t have to explicitly set the request header on the XMLHttpRequest object. The XMLHttpRequest object recognizes that the incoming data type is an instance of FormData and configates the appropriate header information.
XMLHttpRequest Progress event-related API
onloadstart
Fired when the XMLHttpRequest object starts transmitting data, which is when the send() method is called (the HTTP request is sent).
xhr.onloadstart = function () {
console.log('Start making requests... ')}Copy the code
onprogress
Fires continuously during the receiving of a response.
The onProgress event handler receives an Event object whose target attribute is an XMLHttpRequest object, and the event contains three additional attributes: Loaded, Total, and lengthComputable.
event.loaded
: Amount of data transferred (number of bytes received).event.total
: Total amount of data (according toContent-Length
Expected number of bytes determined by the response header).event.lengthComputable
: Boolean value for whether progress information is available.
With this information, you can create an Ajax request progress bar.
const xhr = new XMLHttpRequest()
xhr.onprogress = function (event) {
if(! event.lengthComputable) {return console.log('Unable to calculate progress')} const percentComplete = event.loaded/event.total * 100 console.log(' percent of progress:${percentComplete}%`)
}
xhr.open('post'.'/server'.true)
xhr.send(null)
Copy the code
onerror
Triggered when a request error occurs. This event is triggered only when an exception occurs at the NetWork level. For an application-level exception, for example, the statusCode returned in the response is 4XX, which is not a NetWork Error event. Therefore, an onError event is triggered instead of an onError event.
xhr.onerror = function(e) {
console.log('Data receiving error')}Copy the code
onabort
Triggered when the abort() method is called to terminate the request.
onload
Fired when the request is successful and the complete response data is received.
The onLoad event can be used instead of the readyStatechange event. Since the onLoad event is triggered when the response is received, there is no need to check the readyState property. Whenever the browser receives a response from the server, regardless of its state, the Load event is triggered.
const xhr = new XMLHttpRequest()
xhr.onload = function onload() {
console.log('Data received completed')
if(xhr.status >= 200 && xhr.status < 300) {
console.log(xhr.responseText)
}
}
xhr.open('post'.'/server'.true)
xhr.send(formData)
Copy the code
To ensure proper execution, the onProgress event handler must be added before calling the open() method.
onloadend
Fired after the request ends, either in success or failure, or after an ERROR, ABORT, or LOAD event is triggered.
xhr.onloadend = function(e) {
console.log('Request ended, status unknown')}Copy the code
Each request starts with the triggering of a loadStart event, followed by one or more progress events, then one of error, ABORT, or Load events, and finally ends with the triggering of a loadEnd event.
The upload properties
XMLHttpRequest can send not only requests, but also files, Ajax file uploads.
After sending the file, you get an XMLHttpRequestUpload object using the xmlHttprequest.upload attribute. From this object, you can know the progress of the upload. The implementation is to listen for events on this object: onLoadStart, onProgress, onabort, onError, onLoad, onTimeout, onloadEnd.
When a file is uploaded, you can get the progress of the upload by specifying a listener for the progress event on the Upload attribute.
const xhr = new XMLHttpRequest()
if (xhr.upload) {
xhr.upload.onprogress = function progress(e) {
if (e.total > 0) {
e.percent = e.loaded / e.total * 100
}
}
}
Copy the code
XMLHttpRequest object receives response related API
After receiving the response, the first step is to check the status property. To verify that the response has returned successfully. Use an HTTP status code of 200 as a sign of success. A status code of 304 indicates that the requested resource has not been modified, can be used directly with the cached version in the browser, and is considered valid.
Response header correlation
Content-Type
: The server tells the client the type and character encoding of the response content. Such as:Content-Type: text/html; charset=utf-8
.Content-Length
: The server tells the client the size of the response entity. Such as:Content-Length: 8368
.Content-Encoding
: The server tells the client to return the compression encoding format. Such as:Content-Encoding: gzip, deflate, br
.
More references: developer.mozilla.org/zh-CN/docs/…
The status attribute
The status property returns an integer representing the HTTP status code that the server responded to. If the server does not return a status code, this property defaults to 200. This property is 0 before the request is issued. This property is read-only.
if (xhr.readyState === 4) {
if(xhr.status >= 200&&xhr.status < 300) {// Process the data returned by the server}}Copy the code
StatusText attribute
The statusText property returns a string representing the status statement sent by the server. Like OK and Not Found. The value of this property is an empty string until the request is sent. If the server does not return a status prompt, the value of this property defaults to OK. This property is read-only.
To detect the status attribute to determine what to do next, do not rely on statusText, which is less reliable across browsers.
The response properties
The Response property represents the data returned by the server. It can be any data type, such as string, object, binary objects, etc., the specific type by XMLHttpRequest. ResponseType attribute decision. This property is read-only.
This property is equal to null if the request is unsuccessful or the data is incomplete.
const xhr = new XMLHttpRequest()
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
console.log(xhr.response)
}
}
Copy the code
The responseText property
The responseText property returns the string received from the server, which is read-only.
if (xhr.readyState === 4) {
if(xhr.status >= 200&& xhr.status < 300) {// Process the server's return data console.log(xhr.responsetext)}}Copy the code
ResponseXML property
If the content type of the response is “text/ XML “or “application/ XML”, this property holds the HTML or XML document object that contains the response data. This property is read-only.
Regardless of the content type, the content of the response body is stored in the responseText property. For non-XML data, the responseXML property will be null.
ResponseURL properties
The responseURL property is a string that represents the url of the server that sent the data. Returns an empty string if the URL is empty. If the URL has an anchor, the content after URL# is deleted. This property returns the url where the data was actually returned in the event of a server-side jump.
const xhr = new XMLHttpRequest()
xhr.open('GET'.'http://example.com/test'.true)
xhr.onload = function() {// return to http://example.com/test
console.log(xhr.responseURL)
}
xhr.send(null)
Copy the code
GetResponseHeader () method
The getResponseHeader() method returns the value of the specified field in the HTTP header, or null if no response has been received from the server or if the specified field does not exist. The method’s arguments are case insensitive.
const xhr = new XMLHttpRequest()
xhr.onload = function onload() {
console.log(xhr.getResponseHeader('Content-Type'))
}
xhr.open('post'.'/server'.true)
xhr.send(null)
Copy the code
If there are multiple fields with the same name, their values are concatenated into a string, separated by commas + Spaces.
The getAllResponseHeaders () method
The getAllResponseHeaders() method returns a string representing all HTTP headers sent by the server. The format is a string. Each header is separated by CRLF (carriage return + line feed). If no response is received from the server, this property is null. If a network error occurs, this property is an empty string.
const xhr = new XMLHttpRequest()
xhr.onload = function onload() {
const responseHeaders = 'getAllResponseHeaders' in xhr ? xhr.getResponseHeaders() : null
}
xhr.open('post'.'/server'.true)
xhr.send(null)
Copy the code
The code above is used to get all the header information returned by the server. The return value might be a string like the following.
content-encoding: gzip\r\n
content-length: 2020\r\n
content-type: text/html; charset=utf-8\r\n
Copy the code
This string needs to be processed to be used correctly.
const str = 'date: Fri, 08 Dec 2017 21:04:30 GMT\r\n'
+ 'content-encoding: gzip\r\n'
function trim(str) {
return str.replace(/^\s*/, ' ').replace(/\s*$/, ' ')}function parseHeaders(headers) {
if(! headers) {return {}
}
const parsed = {}
let key, val, i
const arr = headers.split(/[\r\n]+/)
arr.forEach((line) => {
i = line.indexOf(':')
key = trim(line.substr(0, i)).toLowerCase()
val = trim(line.substr(i + 1))
if (key) {
parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val
}
})
return parsed
}
//{date: "Fri, 08 Dec 2017 21:04:30 GMT", content-encoding: "gzip"}
console.log(parseHeaders(str))
Copy the code
Refer to the article
Book.douban.com/subject/105…
Juejin. Cn/post / 684490…
Segmentfault.com/a/119000000…
www.html5rocks.com/zh/tutorial…
Imququ.com/post/four-w…
www.zhihu.com/question/28…
Javascript.ruanyifeng.com/bom/ajax.ht…