Skip to content

Instantly share code, notes, and snippets.

@imthenachoman
Last active October 12, 2016 17:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save imthenachoman/8b4bbc1e4aa39fc5e6ef to your computer and use it in GitHub Desktop.
Save imthenachoman/8b4bbc1e4aa39fc5e6ef to your computer and use it in GitHub Desktop.
cross-browser (IE 8+) XMLHttpRequest that reuses an existing request for recurring requets
/* nXHR
* ----------------------------------------------------------------------------
* cross-browser (IE 8+) XMLHttpRequest that reuses an existing request for recurring requets
*
* url : https://gist.github.com/imthenachoman/8b4bbc1e4aa39fc5e6ef
* author : Anchal Nigam
* e-mail : imthenachoman@gmail.com
*
* Copyright (c) 2015 Anchal Nigam (imthenachoman@gmail.com)
* Licensed under the MIT license: http://opensource.org/licenses/MIT
* ----------------------------------------------------------------------------
*
* References:
* - https://github.com/ilinsky/xmlhttprequest
* - http://www.quirksmode.org/js/xmlhttp.html
*/
var nXHR = nXHR || (function()
{
// keep track of each instance
var instanceID = 0, runningXHRs = {};
// we need to clean up memory on window unload
var onWindowUnload = function()
{
for(var i in runningXHRs)
{
with(runningXHRs[i])
{
clearInterval(timerID);
onreadystatechange = new window.Function;
}
}
};
// cross browser to attach the event
if(window.addEventListener)
{
window.addEventListener("unload", onWindowUnload);
}
else
{
window.attachEvent("onunload", function(){ onWindowUnload.call(window); });
}
// do the actual request
var doRequest = function(id)
{
// find the one we want to do
var xhr = runningXHRs[id];
// notify we're starting
xhr.onStart();
// open it
xhr.open(xhr.postData ? "POST" : "GET", xhr.url, xhr.async);
// set user provided headers
for(var headerName in xhr.requestHeaders)
{
xhr.setRequestHeader(headerName, xhr.requestHeaders[headerName]);
}
// send it
xhr.send(xhr.postData);
};
/*
* the main function to make an actual call
*
* parameters:
* options required {}
* options.url required url for the request
* options.onComplete required function(success, status, responseText, responseXML)
* success true if the call was successful; else false
* status call status number (i.e. 200)
* responseText responseText
* responseXML responseXML
* options.async true or false if the call should be async; defaults to true
* options.requestHeaders hash of header keys and values
* options.postData post data
* options.interval how often this request should be run
* options.onStart function()
* called before the request is started/sent
*/
var main = function(options)
{
// create an xhr
var xhr = new XMLHttpRequest();
// attach some properties
xhr.id = ++instanceID;
xhr.url = options.url;
xhr.async = options.async === false ? false : true;
xhr.requestHeaders = options.requestHeaders || {};
xhr.postData = options.postData;
xhr.interval = options.interval;
xhr.timerID = 0;
xhr.onStart = options.onStart || function(){};
// set some default headers
if(!("User-Agent" in xhr.requestHeaders)) xhr.requestHeaders["User-Agent"] = "XMLHTTP/1.0";
if(xhr.postData && !("Content-type" in xhr.requestHeaders)) xhr.requestHeaders["Content-type"] = "application/x-www-form-urlencoded";
// save it for future access
runningXHRs[xhr.id] = xhr;
// on state change
xhr.onreadystatechange = function()
{
// if we're not done then continue
if(this.readyState != 4) return;
// if we're done then run the onComplete function
options.onComplete(this.status == 200, this.status, this.responseText, this.responseXML);
// if we're running this on a continuous interval
if(this.interval)
{
// save an instance to the xhr object
var that = this;
// set a timer
that.timerID = setTimeout(function()
{
// do the request
doRequest(that.id);
}, this.interval);
}
// else we're done with for this instance
else
{
// clean up to avoid memory leaks
this.onreadystatechange = new window.Function;
// we're done so remove it from the running list
delete runningXHRs[this.id];
}
};
// do the request
doRequest(xhr.id);
// if we have an interval then we want to return the instance ID so we can start/stop it later
if(options.interval) return xhr.id;
};
// stop the timer for an instance ID
main.stop = function(id)
{
var xhr = runningXHRs[id];
clearInterval(xhr.timerID);
xhr.timerID = 0;
};
// start the timer for an instance ID
main.start = function(id)
{
var xhr = runningXHRs[id];
clearInterval(xhr.timerID);
doRequest(id);
};
return main;
})();
/* nXHR | https://gist.github.com/imthenachoman/8b4bbc1e4aa39fc5e6ef/ | Copyright (c) 2015 Anchal Nigam (imthenachoman@gmail.com) | MIT license (http://opensource.org/licenses/mit) */
var nXHR=nXHR||(function(){var instanceID=0,runningXHRs={};var onWindowUnload=function(){for(var i in runningXHRs){with(runningXHRs[i]){clearInterval(timerID);onreadystatechange=new window.Function}}};if(window.addEventListener){window.addEventListener("unload",onWindowUnload)}else{window.attachEvent("onunload",function(){onWindowUnload.call(window)})}var doRequest=function(id){var xhr=runningXHRs[id];xhr.onStart();xhr.open(xhr.postData?"POST":"GET",xhr.url,xhr.async);for(var headerName in xhr.requestHeaders){xhr.setRequestHeader(headerName,xhr.requestHeaders[headerName])}xhr.send(xhr.postData)};var main=function(options){var xhr=new XMLHttpRequest();xhr.id=++instanceID;xhr.url=options.url;xhr.async=options.async===false?false:true;xhr.requestHeaders=options.requestHeaders||{};xhr.postData=options.postData;xhr.interval=options.interval;xhr.timerID=0;xhr.onStart=options.onStart||function(){};if(!("User-Agent"in xhr.requestHeaders))xhr.requestHeaders["User-Agent"]="XMLHTTP/1.0";if(xhr.postData&&!("Content-type"in xhr.requestHeaders))xhr.requestHeaders["Content-type"]="application/x-www-form-urlencoded";runningXHRs[xhr.id]=xhr;xhr.onreadystatechange=function(){if(this.readyState!=4)return;options.onComplete(this.status==200,this.status,this.responseText,this.responseXML);if(this.interval){var that=this;that.timerID=setTimeout(function(){doRequest(that.id)},this.interval)}else{this.onreadystatechange=new window.Function;delete runningXHRs[this.id]}};doRequest(xhr.id);if(options.interval)return xhr.id};main.stop=function(id){var xhr=runningXHRs[id];clearInterval(xhr.timerID);xhr.timerID=0};main.start=function(id){var xhr=runningXHRs[id];clearInterval(xhr.timerID);doRequest(id)};return main})();
function process(data)
{
console.log(data.success + " | " + data.status + " | " + data.text.length + " | " + data.xml);
}
// a simple get request
nXHR("http://www.company.com", process);
// with some options and post data
nXHR("http://www.company.com", process, {
"async" : false,
"requestHeaders" : {
"someHeaderName" : "someHeaderValue",
"someOtherHeadeName" : "someOtherHeaderValue"
},
"postData" : "some data to post"
});
// a request that runs ever 5 seconds
// with some options and post data
var id = nXHR("http://www.company.com", process, {
"async" : false,
"requestHeaders" : {
"someHeaderName" : "someHeaderValue",
"someOtherHeadeName" : "someOtherHeaderValue"
},
"interval" : 5000
});
// stop it
nXHR.stop(id);
// start it
nXHR.start(id);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment