diff options
Diffstat (limited to 'sca-cpp/trunk/modules/js/htdocs/component.js')
-rw-r--r-- | sca-cpp/trunk/modules/js/htdocs/component.js | 152 |
1 files changed, 109 insertions, 43 deletions
diff --git a/sca-cpp/trunk/modules/js/htdocs/component.js b/sca-cpp/trunk/modules/js/htdocs/component.js index a34ebfac92..0a8ec5f5d5 100644 --- a/sca-cpp/trunk/modules/js/htdocs/component.js +++ b/sca-cpp/trunk/modules/js/htdocs/component.js @@ -184,43 +184,113 @@ HTTPBindingClient.jsonResult = function(http) { }; /** - * Schedule async requests, and limit to 4 concurrent running requests. + * Schedule async requests, limiting the number of concurrent running requests. */ HTTPBindingClient.queuedRequests = new Array(); -HTTPBindingClient.runningRequests = 0; -HTTPBindingClient.scheduleAsyncRequest = function(f) { +HTTPBindingClient.runningRequests = new Array(); +HTTPBindingClient.concurrentRequests = 2; + +HTTPBindingClient.scheduleAsyncRequest = function(f, cancelable) { + //debug('schedule async request, running ' + HTTPBindingClient.runningRequests.length + ' queued ' + HTTPBindingClient.queuedRequests.length); + // Queue the request function - HTTPBindingClient.queuedRequests.push(f); + var req = new Object(); + req.f = f; + req.cancelable = cancelable; + req.canceled = false; + HTTPBindingClient.queuedRequests.push(req); + + // Execute any requests in the queue + setTimeout(function() { + HTTPBindingClient.runAsyncRequests(true); + }, 0); + return true; +}; - // Execute requests in the queue - (function runAsyncRequests() { - // Stop now if we already have enough requests running or there's no request in the queue - //debug('runAsyncRequests', 'running', HTTPBindingClient.runningRequests, 'queued', HTTPBindingClient.queuedRequests.length); - if(HTTPBindingClient.runningRequests >= 4 || HTTPBindingClient.queuedRequests.length == 0) +HTTPBindingClient.forgetRequest = function(req) { + req.http = null; + + // Remove a request from the list of running requests + for (i in HTTPBindingClient.runningRequests) { + if (HTTPBindingClient.runningRequests[i] == req) { + HTTPBindingClient.runningRequests.splice(i, 1); + //debug('forget async request, running ' + HTTPBindingClient.runningRequests.length + ' queued ' + HTTPBindingClient.queuedRequests.length); return true; + } + } + return false; +}; + +HTTPBindingClient.cancelRequests = function() { + //debug('cancel async requests, running ' + HTTPBindingClient.runningRequests.length + ' queued ' + HTTPBindingClient.queuedRequests.length); + + // Cancel any cancelable in flight HTTP requests + for (i in HTTPBindingClient.queuedRequests) { + var req = HTTPBindingClient.queuedRequests[i]; + if (req.cancelable) + req.canceled = true; + } + for (i in HTTPBindingClient.runningRequests) { + var req = HTTPBindingClient.runningRequests[i]; + if (req.cancelable) { + req.canceled = true; + if (req.http) { + req.http.abort(); + req.http = null; + //debug('abort async request, running ' + HTTPBindingClient.runningRequests.length + ' queued ' + HTTPBindingClient.queuedRequests.length); + } + } + } - // Run the first request in the queue - var req = HTTPBindingClient.queuedRequests.shift(); - HTTPBindingClient.runningRequests++; - setTimeout(function runAsyncRequest() { + // Flush the queue + setTimeout(function() { + HTTPBindingClient.runAsyncRequests(true); + }, 0); +} + +HTTPBindingClient.runAsyncRequests = function(fromui) { + // Stop now if we already have enough requests running or there's no request in the queue + if(HTTPBindingClient.runningRequests.length >= HTTPBindingClient.concurrentRequests || HTTPBindingClient.queuedRequests.length == 0) + return true; + + // Run the first request in the queue + var req = HTTPBindingClient.queuedRequests.shift(); + if (!req.canceled) { + HTTPBindingClient.runningRequests.push(req); + //debug('run async request, running ' + HTTPBindingClient.runningRequests.length + ' queued ' + HTTPBindingClient.queuedRequests.length); + var runAsyncRequest = function() { + if (req.canceled) { + HTTPBindingClient.forgetRequest(req); + //debug('canceled timed async request, running ' + HTTPBindingClient.runningRequests.length + ' queued ' + HTTPBindingClient.queuedRequests.length); + return false; + } try { - return req(function asyncRequestDone() { + req.http = new XMLHttpRequest(); + return req.f(req.http, function asyncRequestDone() { // Execute any requests left in the queue - HTTPBindingClient.runningRequests--; - runAsyncRequests(); + HTTPBindingClient.forgetRequest(req); + //debug('done async request, running ' + HTTPBindingClient.runningRequests.length + ' queued ' + HTTPBindingClient.queuedRequests.length); + HTTPBindingClient.runAsyncRequests(false); return true; }); } catch(e) { // Execute any requests left in the queue - HTTPBindingClient.runningRequests--; - runAsyncRequests(); + HTTPBindingClient.forgetRequest(req); + //debug('err async request, running ' + HTTPBindingClient.runningRequests.length + ' queued ' + HTTPBindingClient.queuedRequests.length); + HTTPBindingClient.runAsyncRequests(false); } - }, 0); + return false; + }; + if (false) + setTimeout(runAsyncRequest, 0); + else + runAsyncRequest(); + } else { + //debug('canceled queued async request, running ' + HTTPBindingClient.runningRequests.length + ' queued ' + HTTPBindingClient.queuedRequests.length); + } - // Execute any requests left in the queue - runAsyncRequests(); - })(); - return true; + // Execute any requests left in the queue + HTTPBindingClient.runAsyncRequests(fromui); }; /** @@ -339,8 +409,7 @@ HTTPBindingClient.prototype.jsonApply = function(req) { // Call asynchronously with a callback if(hascb) { var u = this.uri; - return HTTPBindingClient.scheduleAsyncRequest(function jsonApplyRequest(done) { - var http = new XMLHttpRequest(); + return HTTPBindingClient.scheduleAsyncRequest(function jsonApplyRequest(http, done) { http.open("POST", u, true); http.setRequestHeader("Accept", "*/*"); http.setRequestHeader("Content-Type", "application/json-rpc"); @@ -371,7 +440,7 @@ HTTPBindingClient.prototype.jsonApply = function(req) { // Send the request http.send(req.data); return req.id; - }); + }, false); } // Call synchronously and return the result or exception @@ -402,16 +471,15 @@ HTTPBindingClient.prototype.get = function(id, cb, mode) { return item; // Pass local result to callback - try { + setTimeout(function() { cb(item); - } catch (cbe) {} + }, 0); } } // Call asynchronously with a callback if(hascb) { - return HTTPBindingClient.scheduleAsyncRequest(function getRequest(done) { - var http = new XMLHttpRequest(); + return HTTPBindingClient.scheduleAsyncRequest(function getRequest(http, done) { http.open("GET", u, true); http.setRequestHeader("Accept", "*/*"); http.onreadystatechange = function() { @@ -420,7 +488,8 @@ HTTPBindingClient.prototype.get = function(id, cb, mode) { // Pass result if different from local result if(http.status == 200) { var xl = http.getResponseHeader("X-Login"); - if(xl != null && xl != '') { + var ct = http.getResponseHeader("Content-Type"); + if(xl != null && xl != '' && ct != null && ct.indexOf('text/html') == 0) { // Detect redirect to a login page try { var le = new HTTPBindingClient.Exception(403, 'X-Login'); @@ -431,7 +500,6 @@ HTTPBindingClient.prototype.get = function(id, cb, mode) { } catch(cbe) {} } - var ct = http.getResponseHeader("Content-Type"); if(http.responseText == '' || ct == null || ct == '') { // Report empty response try { @@ -467,7 +535,7 @@ HTTPBindingClient.prototype.get = function(id, cb, mode) { // Send the request http.send(null); return true; - }); + }, true); } // Call synchronously and return the result or exception @@ -477,7 +545,8 @@ HTTPBindingClient.prototype.get = function(id, cb, mode) { http.send(null); if(http.status == 200) { var xl = http.getResponseHeader("X-Login"); - if(xl != null && xl != '') { + var ct = http.getResponseHeader("Content-Type"); + if(xl != null && xl != '' && ct != null && ct.indexOf('text/html') == 0) { // Detect redirect to a login page var le = new HTTPBindingClient.Exception(403, 'X-Login'); if(window.onloginredirect) @@ -504,8 +573,7 @@ HTTPBindingClient.prototype.post = function (entry, cb) { // Call asynchronously with a callback if(hascb) { var u = this.uri; - return HTTPBindingClient.scheduleAsyncRequest(function postRequest(done) { - var http = new XMLHttpRequest(); + return HTTPBindingClient.scheduleAsyncRequest(function postRequest(http, done) { http.open("POST", u, true); http.setRequestHeader("Accept", "*/*"); http.setRequestHeader("Content-Type", "application/atom+xml"); @@ -529,7 +597,7 @@ HTTPBindingClient.prototype.post = function (entry, cb) { // Send the request http.send(entry); return true; - }); + }, false); } // Call synchronously @@ -562,8 +630,7 @@ HTTPBindingClient.prototype.put = function(id, entry, cb, mode) { // Call asynchronously with a callback if(hascb) { - return HTTPBindingClient.scheduleAsyncRequest(function putRequest(done) { - var http = new XMLHttpRequest(); + return HTTPBindingClient.scheduleAsyncRequest(function putRequest(http, done) { http.open("PUT", u, true); http.setRequestHeader("Accept", "*/*"); http.setRequestHeader("Content-Type", "application/atom+xml"); @@ -599,7 +666,7 @@ HTTPBindingClient.prototype.put = function(id, entry, cb, mode) { // Send the request http.send(entry); return true; - }); + }, false); } // Call synchronously @@ -640,8 +707,7 @@ HTTPBindingClient.prototype.del = function(id, cb, mode) { // Call asynchronously with a callback if(hascb) { - return HTTPBindingClient.scheduleAsyncRequest(function delRequest(done) { - var http = new XMLHttpRequest(); + return HTTPBindingClient.scheduleAsyncRequest(function delRequest(http, done) { http.open("DELETE", u, true); http.setRequestHeader("Accept", "*/*"); http.onreadystatechange = function() { @@ -665,7 +731,7 @@ HTTPBindingClient.prototype.del = function(id, cb, mode) { // Send the request http.send(null); return true; - }); + }, false); } // Call synchronously |