[removed] xmlhttprequest randomly stuck at Ready S

2019-03-06 07:50发布

问题:

I've been working on a Windows gadget (meaning the "browser" is Internet Explorer) that queries specified subnet addresses for information. Now, it sometimes does this at a relatively quick pace (roughly every 5 seconds) and it works well enough. However, sometimes it will get stuck at ready state 1 and will just stay there forever. Whenever the gadget tries to redo the function for getting the xmlhttprequest and getting information from it it will stay at state 1. This is easily replicable when opening multiple instances of the gadget and then closing all but one of them. At that point, the one that's still open will almost always get stuck in this state. I feel like it might have something to do with them all accessing the same website, or it may just have to do with xmlhttprequests being stopped mid-transmission and that preventing another from working. Below is the relevant code.

//Reference to this for the inner function
var me = this;
var request = new XMLHttpRequest();
request.onreadystatechange = onReadyStateChange;
var url = this.url;
//Make the URL random to prevent being cached
url += ("&a=" + ((new Date()).getTime()));
Trace(DEBUG_COMM, "Sase.updateStatus url: " + url);
request.open("GET", url, true);
request.send();   // fire off the request, calls httpRequestReadyStateChange as things continue
Trace(DEBUG_COMM, "Request sent" + request.readyState); 
function onReadyStateChange() {Trace(DEBUG_COMM, "Sase.httpRequestReadyStateChange: state=" + request.readyState);
    if (4 == request.readyState) {
        Trace(DEBUG_COMM, "Sase.httpRequestReadyStateChange: status=" + request.status);

        if (request.status == 200) {
            Trace(DEBUG_COMM, "retrieved html: " + request.responseText);
            var results = request.responseText;
            var resultsString = request.responseText.toString();
            Trace(DEBUG_COMM, "results String: " + resultsString);
            me.ParseStatusData(resultsString);
        }
        else {
            //me.commError(request.status);
        }

        request = null;
    }
}

回答1:

Well it looks like I figured it out. I had a feeling it was an unresolved request, since it only happens when instances of it are closed (meaning that if one of them is closed while in communication with the server it stays in communication forever and no one else can access the server) and it appears that is the case. I made some modifications to the code in multiple areas and basically what it comes down to is when the gadget closes it makes sure to abort all of the requests. The requests are now instance variables (to allow for the aborting of them), but are still made new everytime they are needed.



回答2:

For those who stumble across this and need a concrete code example, here you go.

I had the same problem and the solution was to re-use the XMLHttpRequest object, to ensure that any previous request was cancelled before initiating a new one. This won't work if you want to have multiple AJAX requests flying around but in my case triggering a new request meant that the last one was no longer needed.

All of the requests on my page went through the same XMLHttpRequest wrapper method which looked like this;

//Declare the XMLHttpRequest object to be re-used
var global_xHttpRequest = null;

function xmlHttpHandler(type, params, complete, postData) {

   //Prevents an issue where previous requests get stuck and new ones then fail
   if (global_xHttpRequest == null) {
       global_xHttpRequest = new XMLHttpRequest();
   } else {
       global_xHttpRequest.abort();
   }

   //Parse out current URL
   var baseURL = window.location.host;
   var svc = "https://" + baseURL + "/processAction?";

   var url = svc + params;

   global_xHttpRequest.open(type, url, true);

   //Add the callback
   global_xHttpRequest.onreadystatechange = complete;

   global_xHttpRequest.send(postData);
}

Which can be used like this:

   xmlHttpHandler("GET", params, completeFnc);