JQuery ajax a misunderstanding

Colleague was a very strange question. Question is described as follows: There is a page when the page is loaded by default sends an asynchronous ajax requests. ** if ** In the case of outstanding requests, refresh the page, it will perform a ajax callback, strangely enough, did not get to the data, with fiddler monitoring, server data is returned. (Here we must note that the request was not completed, if the simulation, you can break point after the open method XMLHttpRequest Then do not perform recurring problem send. As to why after the open, there will be explained later). This question, let us first look at how the package JQuery ajax (here version 1.4.1), the source code is as follows:

 1 ajax: function( origSettings ) {
 2     var s = jQuery.extend(true, {}, jQuery.ajaxSettings, origSettings);
 3     var jsonp, status, data,
 4             callbackContext = origSettings && origSettings.context || s,
 5             type = s.type.toUpperCase();
 6     // convert data if not already a string
 7     ....这里省略中间jsonp的实现
 8     var requestDone = false;
 9 
10     // Create the request object
11     var xhr = s.xhr();
12     
13     .....
14     // Wait for a response to come back
15     var onreadystatechange = xhr.onreadystatechange = function( isTimeout ) {
16         // The request was aborted
17     if ( !xhr || xhr.readyState === 0 || isTimeout === "abort" ) {
18             .....
19 
20     // The transfer is complete and the data is available, or the request timed out
21     } else if ( !requestDone && xhr && (xhr.readyState === 4 || isTimeout === "timeout") ) {
22         requestDone = true;
23         xhr.onreadystatechange = jQuery.noop;
24 
25         status = isTimeout === "timeout" ?
26             "timeout" :
27             !jQuery.httpSuccess( xhr ) ?
28                 "error" :
29                 s.ifModified && jQuery.httpNotModified( xhr, s.url ) ?
30                     "notmodified" :
31                     "success";
32 
33         var errMsg;
34 
35         if ( status === "success" ) {
36             // Watch for, and catch, XML document parse errors
37             try {
38                 // process the data (runs the xml through httpData regardless of callback)
39                 data = jQuery.httpData( xhr, s.dataType, s );
40             } catch(err) {
41                 status = "parsererror";
42                 errMsg = err;
43             }
44         }
45 
46         // Make sure that the request was successful or notmodified
47         if ( status === "success" || status === "notmodified" ) {
48             // JSONP handles its own success callback
49             if ( !jsonp ) {
50                 success();
51             }
52         } else {
53             jQuery.handleError(s, xhr, status, errMsg);
54         }
55 
56         // Fire the complete handlers
57         complete();
58 
59         if ( isTimeout === "timeout" ) {
60             xhr.abort();
61         }
62 
63         // Stop memory leaks
64         if ( s.async ) {
65             xhr = null;
66         }
67         }
68     };
69 
70     ....
71 
72     // Send the data
73     try {
74         xhr.send( type === "POST" || type === "PUT" || type === "DELETE" ? s.data : null );
75     } catch(e) {
76         jQuery.handleError(s, xhr, null, e);
77         // Fire the complete handlers
78         complete();
79     }
80 
81     
82 
83     function success() {
84         // If a local callback was specified, fire it and pass it the data
85         if ( s.success ) {
86             s.success.call( callbackContext, data, status, xhr );
87         }
88 
89         // Fire the global callback
90         if ( s.global ) {
91             trigger( "ajaxSuccess", [xhr, s] );
92         }
93     }
94 
95     .....
96 
97     // return XMLHttpRequest to allow aborting the request etc.
98     return xhr;
99   }

There is the most critical, is the realization ** onreadystatechange **. This implementation which has two branches, the first branch is completed trigger mechanism ajax, nothing to say, we just look at the second branch.

if ( !requestDone && xhr && (xhr.readyState === 4 || isTimeout === "timeout") )

Note that the judgment conditions xhr.readyState === 4 That is when readyState XMLHttpRequest object is equal to 4, JQ will think the whole ajax request is over. Then call success method. We look to achieve success in:

 1   function success() {
 2         // If a local callback was specified, fire it and pass it the data
 3     if ( s.success ) {
 4         s.success.call( callbackContext, data, status, xhr );
 5     }
 6 
 7     // Fire the global callback
 8     if ( s.global ) {
 9         trigger( "ajaxSuccess", [xhr, s] );
10     }
11    }

Code is very simple, is to call a callback function that we define in which $ .ajax configuration object passed. Well, since when we refresh the page, call our callback function, then there must execute the code here. So here's the code executed on behalf of the moment will refresh the page, ** onreadystatechange ** is triggered, and should be completed in ajax. This time, we must look at what JQ considered complete ajax condition yes. JQ will remain a state called a status of their own values. code show as below:

  status = isTimeout === "timeout" ?
    "timeout" :!jQuery.httpSuccess( xhr ) ?
        "error" :
        s.ifModified && jQuery.httpNotModified( xhr, s.url ) ?
        "notmodified" :
        "success";

JQuery.httpSuccess we look at the implementation of this method:

 1    httpSuccess: function( xhr ) {
 2     try {
 3         // IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
 4         return !xhr.status && location.protocol === "file:" ||
 5             // Opera returns 0 when status is 304
 6             ( xhr.status >= 200 && xhr.status < 300 ) ||
 7             xhr.status === 304 || xhr.status === 1223 || xhr.status === 0;
 8     } catch(e) {}
 9 
10     return false;
11   }

 

The key in this state xhr.status === 0 value. Of course, first I ignored here, leading around a lot of detours, as to why key here, behind us said.
Since when is a problem in this judgment, then we will recover refresh the page, xhr.status in the end what state the value of it? I wrote a test code, the code is as follows:

 1  // Create the request object
 2   var xhr = s.xhr();
 3 
 4   var _l = window.localStorage.length;
 5   if (!xhr.id) xhr.id = _l;
 6   window.localStorage['xhr_id' + _l] = xhr.id;
 7   window.localStorage['xhr_readyState' + _l] = xhr.readyState;
 8   
 9   ....
10   
11   // Make sure that the request was successful or notmodified
12    if (status === "success" || status === "notmodified") {
13    window.localStorage['onchange_end_xhr_id' + _l] = xhr.id;
14    window.localStorage['onchange_end_status' + _l] = status;
15    window.localStorage['onchange_end_xhr_status' + _l] = xhr.status;
16    window.localStorage['onchange_end_xhr' + _l] = xhr.responseText;
17    window.localStorage['onchange_end_xhr_lastModified' + _l] = lastModified;
18    window.localStorage['onchange_end_xhr_etag' + _l] = etag;              

 

Join logic state record in the code of JQ, because each time you refresh the browser page life cycle will end and start again, so here is a warehouse to record the status value. Record the final results were as follows:

{{: Marketing Group: Technical problem solution highlights: javascript: jq problem screenshots .png |}}

** state is 0! ! ! ! **, meaning that the server does not have any return (so we simulate, only just open, do not send).

After I reviewed the information:

** 1.readyState There are four state value. Reads as follows: **

done DONE (numeric value 4) The data transfer has been completed or something went wrong during the transfer (e.g. infinite redirects).

In other words, not just the server returns data will be assigned to 4, and is in the process of acquiring the data the wrong time, it is also set to 4.

** see the words on 2.wiki: **

If the open method of the XMLHttpRequest object was invoked with the third parameter set to true for an asynchronous request, the onreadystatechange event listener will be automatically invoked for each of the following actions that change the readyState property of the XMLHttpRequest object.

In other words, as long as the XMLHttpRequest object to perform the open method, it will automatically when the readyState value changes, call onreadystatechange event.

** Conclusion: **
When you refresh the page when the asynchronous ajax requests if this time is not yet complete, but open, then the browser thinks the end of this request to obtain data failed. So this time the readyState is set to 4 (Then you call
onreadystatechange event), but the state is 0. The JQ in determining success, state === 0 can be considered successful (do not know why also believe that the success of)! ! !
So we still call the success callback method, but did not obtain any data.


'Reference: \\
HTTPS: \\ //en.wikipedia.org/wiki/XMLHttpRequest
HTTPS: \\ //xhr.spec.whatwg.org/#interface-xmlhttprequest
https://developer.mozilla.org/ CN-zh / docs / Web / API / the XMLHttpRequest \\
https://www.w3.org/TR/XMLHttpRequest1/

Guess you like

Origin www.cnblogs.com/wzgblogs/p/12145678.html