Everyone is familiar with Ajax. However, because many frameworks or libraries have encapsulated the network request, many beginners only know it and do not know why. So today we’ll take a closer look at how Ajax works and the key steps to encapsulate Ajax.

At the heart of Ajax is the XMLHttpRequest object. So let’s first create an XMLHTTPRequest object var XHR = new XMLHTTPRequest (); .

Note: the content mentioned in this article is not compatible with the old IE, there are students who want to know the relevant content of ActiveXObject.


XMLHttpRequest

In the first step of using the XMLHttpRequest object, we first initialize the request parameter by calling the open method, xhr.open(‘get’,’/test’,true). Despite the name, the request has not yet been sent.

open(method, url[, async, username, password])

  • Method: Indicates the request type, such as GET and POST
  • Url: request address (there is a same-origin restriction here, which is a cross-domain problem we often see)
  • Async: Whether to send asynchronous requests. This parameter is optional. The default value is true.
  • HTTP (s)://username:password@url username&password: this parameter is optional.

If you call the open method and then call it again, you call abort, which we describe later.

If we want to bind some actions to the request, this is the time to start. Common operations are as follows:

setRequestHeader(key, value)

As the name implies, this method is used to set the request header content.

  • Key: name of the request header to be set
  • Value: indicates the value of the request header

overrideMimeType(type)

Overrides the MIME type returned by the server. This method tells the server what type of data you want.

Note: These operations must be defined before the SEND method. Otherwise, in the case of setRequestHeader, what’s the point of setting it up after you’ve already sent the request?

At this point, we can send the request by calling the send method, xhr.send(null).

send(data)

Sending a request, if synchronous, blocks code execution until a response is received from the server.

  • Data: data sent to the server. To be compatible with different browsers, you need to pass in the null parameter even if you don’t need to pass data.

readyStateChanhe()

This function is triggered every time the readyState value changes.

getResponseHeader(name)

Gets the value of the specified response header. The parameter is the name of the response header and is case insensitive.

getAllResponseHeaders()

Gets the headers for all HTTP responses sent by the server.

The readyState property indicates the state of the request, along with the HTTP request’s entire life cycle, and its value indicates the phase of the request at this point, as follows:

readyState

The numerical describe
0 Initialization,open() has not been called
1 Open () has been called, but send has not
2 Return header information has been obtained
3 Downloading returning body information
4 Request is completed

There are a few more commonly used attributes

The name of the meaning
responseText Text of the response
status The status code of the response
statusText Response status information
responseXML When the response content is in the “text/ XML” or “application/ XML” format, the value of this attribute is the XMLDOM document of the response data.

Let’s do a test with the following code

var xhr = new XMLHttpRequest();
console.log(xhr.readyState)
xhr.onreadystatechange = function(){
    console.log('-- -- -- -- -- -)
    console.log('readyState:' + xhr.readyState)
    console.log('ResponseHeaders:' + xhr.getAllResponseHeaders())
    console.log('ResponseText:' + xhr.responseText.length)
    console.log('-- -- -- -- -- -)
}
xhr.open('get'.'/')
xhr.send(null)
Copy the code

As you can see visually in the figure below, the readyState value is 0 when the XMLHttpRequest object is created.

  1. When we call the send method, the readyState is set to 2 and the responseHeader is available.
  2. The response data starts to download and readyState changes to 3
  3. When the response data is downloaded, readyState changes to 4.

abort()

Cancel the response. Calling this method terminates the sent request. Let’s try adding a sentence at the end of the previous code.

xhr.abort();
consoleThe log (XHR. ReadyState);Copy the code

That is, after send, it does not attempt to request data, but simply canceles it, and we find that ABORT sets readyState to 0.

In addition, XMLHttpRequest also has an important attribute called withCredentials. Cookies are automatically carried in the request header for same-domain requests, but not for cross-domain requests, unless the withCredentials value is set to true (the default is false). In addition, you need to set access-Control-allow-credentials :true in the response header of the server. Not only that, the access-Control-Allow-Origin value must also be the domain name of the current page.


encapsulation

At this point, we’ve finally covered some common concepts for XMLHttpRequest. Next, we’ll try to wrap a simple JAX request ourselves that supports GET and POST.

function ajax(url, option){
    option = option || {};
    var method = (option.method || 'GET').toUpperCase(),
        async = option.async === undefined ? true : option.async,
        params = handleParams(option.data);
    var xhr = new XMLHttpRequest();
    if(async){
        xhr.onreadystatechange = function () {
            if (xhr.readyState == 4){ callback(option,xhr); }}; }if (method === 'GET'){
        xhr.open("GET",url + '? ' + params, async);
        xhr.send(null)}else if (method === 'POST'){
        xhr.open('POST', url, async);
        xhr.setRequestHeader('Content-Type'.'application/x-www-form-urlencoded');
        xhr.send(params);
    }
    if(!async){
        callback(option,xhr);
    }
    function callback(opt,obj){
        var status = obj.status;
        if (status >= 200 && status < 300 ){
            opt.success && opt.success(obj.responseText,obj.responseXML);
        }else{ opt.fail && opt.fail(status); }}function handleParams(data) {  
        var arr = [];
        for (var i in data) {
            arr.push(encodeURIComponent(i) + '=' + encodeURIComponent(data[i]));
        }
        return arr.join('&'); }}// Test the call
ajax('/xxx', {method:'POST'.data: {key: 'test'
    },
    success:function(){
        console.log('success')},fail:function(){
        console.log('fail')}});Copy the code

summary

In fact, ajax implementation principle is not complex, complex is fault tolerance, compatibility and other processing, use as far as possible to use the library or framework provided by the package, to avoid unnecessary vulnerabilities.