1 /*/////////////////////////////////////////////////////////////////////////////2 //3 AJAX DEFINITION (BEGIN) //4 */5 /**6 * Description: Manage ajax connections with a queue model.7 * Author: gerardooscarjt@gmail.com8 * Date: 2013/31/019 * Typical use:10 11 var ajax = new Ajax();12 ajax.setUrl('http://example.com/path');13 ajax.setMethod('post');14 ajax.setData({'name':'a','age':'22'};15 ajax.callback.done = function(xhr) {16 // ...17 };18 ajax.callback.error = function(xhr) {19 // ...20 };21 ajax.send();22 23 */24 var Ajax = function() {25 26 Ajax.prototype.requests.push(this);27 28 this._id = Ajax.prototype.id_generator;29 Ajax.prototype.id_generator++;30 31 this.callback = {32 done:null,33 error:null,34 progress:null,35 presend:null36 };37 38 this._method = 'get';39 this._async = true;40 this._url = '';41 this._data = null;42 this._retries = 3;43 this._xhr = null;44 this._timeout = 3000;45 46 }47 48 Ajax.prototype.requests = [];49 Ajax.prototype.queue = [];50 Ajax.prototype.id_generator = 0;51 Ajax.prototype.concurrency_limit = 4;52 53 /// METHOD ///54 Ajax.prototype.setMethod = function(method) {55 if (!this.isQueued())56 this._method = method;57 };58 Ajax.prototype.getMethod = function(method) {59 return this._method;60 };61 62 /// URL ///63 Ajax.prototype.setUrl = function(url) {64 if (!this.isQueued())65 this._url = url;66 };67 Ajax.prototype.getUrl = function() {68 return this._url;69 };70 71 /// DATA ///72 Ajax.prototype.setData = function(data) {73 if (!this.isQueued())74 this._data = data;75 };76 Ajax.prototype.getData = function () {77 return this._data;78 };79 80 /// TIMEOUT ///81 Ajax.prototype.setTimeout = function(timeout) {82 this._timeout = timeout;83 };84 Ajax.prototype.getTimeout = function() {85 return this._timeout;86 };87 88 /// IS QUEUED ///89 Ajax.prototype.isQueued = function () {90 return Ajax.prototype.queue.indexOf(this) > -1;91 };92 93 Ajax.prototype.send = function() {94 if (!this.isQueued()) {95 //logger.log(this._id + ' no está en la cola: encolando...');96 ajax_stats[this._id+'.'+this._retries] = {'delay':NaN,'waiting':NaN,'request':NaN,'server_delay':'undefined','status':'queued'};97 ajax_stats[this._id+'.'+this._retries].delay = new Date().getTime();98 Ajax.prototype.queue.push(this);99 Ajax._move();100 } else {101 //logger.log('ya está en la cola'); 102 }103 };104 105 /**106 * Close connection107 */108 Ajax.prototype._close = function() {109 Ajax.prototype.concurrency_limit++;110 this._retries--;111 if (this._retries > 0) {112 this.send();113 }114 Ajax._move();115 116 };117 118 /**119 * Returns true if abort has been performed120 */121 Ajax.prototype.abort = function() {122 if ( null != this._xhr && this._xhr.readyState != 4) {123 // The request is on the way. It must be cancelled124 ajax_stats[this._id+'.'+this._retries].request = new Date().getTime();125 ajax_stats[this._id+'.'+this._retries].status = 'aborted';126 127 this._xhr.abort();128 delete this._xhr;129 this._xhr = null;130 this._retries--;131 Ajax.prototype.concurrency_limit++;132 return true;133 }134 return false;135 };136 137 /// PRIVATE METHODS (I WOULD LIKE) ///138 Ajax.prototype._send = function() {139 var that = this;140 141 //logger.log('Send request for '+this._id);142 143 this._xhr = new XMLHttpRequest({mozSystem:true});144 this._xhr.open(this._method, this._url, this._async);145 this._xhr.timeout = this._timeout;146 147 this._xhr.onreadystatechange = function(event) {148 if(null != that._xhr && that._xhr.readyState == XMLHttpRequest.DONE) {149 ajax_stats[that._id+'.'+that._retries].request = new Date().getTime();150 ajax_stats[that._id+'.'+that._retries].server_delay = that._xhr.responseText;151 if (that._xhr.status == 0) {152 ajax_stats[that._id+'.'+that._retries].status = 'retry';153 } else {154 ajax_stats[that._id+'.'+that._retries].status = 'done';155 results[that._id] = that._xhr.responseText;156 157 that._retries = 0;158 }159 that._close();160 }161 };162 163 this._xhr.onerror = function(event) {164 ajax_stats[that._id+'.'+that._retries].status = 'error';165 that._close();166 };167 168 this._xhr.send();169 ajax_stats[this._id+'.'+this._retries].waiting = new Date().getTime();170 ajax_stats[that._id+'.'+that._retries].status = 'sent';171 172 };173 174 175 /// STATIC METHODS ///176 177 // Abort all current requests178 Ajax._abort_all = function() {179 for (var k in Ajax.prototype.requests) {180 var a = Ajax.prototype.requests[k];181 a.abort() && a.send();182 }183 };184 185 /* Move queue */186 Ajax._move = function() {187 188 if (window.navigator.onLine) {189 while (Ajax.prototype.concurrency_limit > 0 && Ajax.prototype.queue.length > 0) {190 var a = Ajax.prototype.queue.shift();191 ajax_stats[a._id+'.'+a._retries].status = 'unqueued';192 a._send();193 Ajax.prototype.concurrency_limit--;194 }195 }196 };197 198 // Initialize onLine and offLine events199 window.addEventListener('online', function() {200 Ajax._move();201 }, true);202 203 window.addEventListener('offline', function() {204 Ajax._abort_all();205 }, true);206 207 /*208 AJAX DEFINITION (END) //209 //210 /////////////////////////////////////////////////////////////////////////////*/211 212 213 214 var ajax_stats_start = new Date().getTime();215 var ajax_stats = {};216 var line_status = [];217 var results = [];218 219 220 221 222 window.addEventListener('load', function(){223 //test1(); 224 225 // Initialize onLine and offLine events226 window.addEventListener('online', function() {227 line_status.push(new Date().getTime());228 }, true);229 230 window.addEventListener('offline', function() {231 line_status.push(new Date().getTime());232 }, true);233 234 235 log_chart = logger.log('CHAT WILL BE RENDERED HERE');236 237 }, true);238 239 240 /**241 * Launch 20 ajax calls242 */243 function test1() {244 245 ajax_stats_start = new Date().getTime();246 ajax_stats = {};247 results = [];248 249 logger.show();250 251 for (var i=0; i<20; i++) {252 var ajax = new Ajax();253 ajax.setUrl('http://www.treeweb.es/request?e='+ajax._id+'&delay=random');254 ajax.callback.done = function(xhr) {255 logger.log('Completed '+ajax._id);256 };257 ajax.send();258 //logger.log('Launched '+ajax._id);259 }260 261 //logger.log(Ajax.prototype.queue);262 263 see_chart();264 }265 266 /**267 * Launch N fast ajax calls268 */269 function test2(n) {270 271 ajax_stats_start = new Date().getTime();272 ajax_stats = {};273 results = [];274 275 logger.show();276 277 for (var i=0; i<n; i++) {278 var ajax = new Ajax();279 ajax.setUrl('http://www.treeweb.es/request?e='+ajax._id+'&delay=0');280 ajax.callback.done = function(xhr) {281 282 };283 ajax.send();284 }285 see_chart();286 }287 288 function see_stats() {289 290 var s = '';291 292 for (k in ajax_stats) {293 s +=294 '<tr>'295 + '<td>' + (k) + ' (server delay ' + ajax_stats[k].server_delay + ')' + '</td>'296 + '<td>' + (ajax_stats[k].delay - ajax_stats_start) + '</td>'297 + '<td>' + (ajax_stats[k].waiting - ajax_stats[k].delay) + '</td>'298 + '<td>' + (ajax_stats[k].request - ajax_stats[k].waiting) + '</td>'299 + '</tr>';300 }301 302 var h = '<tr> <td>id</td> <td>delay</td> <td>waiting</td> <td>request</td> </tr>';303 s = '<table>' + h + s + '</table>';304 305 logger.log(s);306 logger.show();307 }308 309 var log_chart = null;310 311 312 function see_chart() {313 314 var ts = new Date().getTime();315 316 // Calc maximum time:317 /*318 var max_t = -1;319 var max_w = 1;320 for (k in ajax_stats)321 if (ajax_stats[k].request > max_t) {322 max_t = ajax_stats[k].request;323 max_w = ajax_stats[k].request - ajax_stats_start;324 }325 */326 327 max_w = ts - ajax_stats_start;328 329 var s = '';330 331 for (k in ajax_stats) {332 333 var delay = ajax_stats[k].delay;334 isNaN(delay) && (delay = ts);335 336 var waiting = ajax_stats[k].waiting;337 isNaN(waiting) && (waiting = ts);338 339 var request = ajax_stats[k].request;340 isNaN(request) && (request = ts);341 342 343 var delay_ms = delay - ajax_stats_start;344 var waiting_ms = waiting - delay;345 var request_ms = request - waiting;346 347 //if ( isNaN(ajax_stats[k].request) ) logger.log('NAAAAN');348 349 var delay_rel = (100 * Math.floor(1000*(delay_ms) / max_w ) / 1000);350 var waiting_rel = (100 * Math.floor(1000*(waiting_ms) / max_w ) / 1000);351 var request_rel = (100 * Math.floor(1000*(request_ms) / max_w ) / 1000);352 353 s += ''354 + '<div class="label">' + (k) + ' (' + ajax_stats[k].status + ') ' + '</div>'355 + '<div class="row">'356 + '<div class="bar bar-delay" style="width:' + delay_rel + '%" title="' + delay_rel + '%">' + delay_ms + 'ms</div>' 357 + '<div class="bar bar-waiting" style="width:' + waiting_rel +'%" title="' + waiting_rel +'%">' + waiting_ms + 'ms</div>'358 + '<div class="bar bar-request" style="width:' + request_rel +'%" title="' + request_rel +'%">' + request_ms + 'ms</div>'359 + '<div class="bar bar-end" ><div></div></div>'360 + '</div>';361 }362 363 // Display seconds364 s += ''365 + '<div class="label"> seconds </div>'366 + '<div class="row">';367 var second_width = (100 * Math.floor(1000*(1000) / max_w ) / 1000);368 var c = 0;369 for (var i = ajax_stats_start+1000; i<ts; i+=1000) {370 c++;371 s += '<div class="bar bar-second" style="width:' + second_width + '%">' + c + '</div>' 372 }373 s += '</div>';374 375 s = '<div class="chart">' + s + '</div>';376 377 378 379 var s2 = '';380 for (var i=0; i<results.length; i++) {381 s2 += '<div style="display:inline-block; border:solid silver 1px; padding:4px;">'+i+' ('+results[i]+')</div>';382 }383 s += '<div>'+s2+'</div>';384 385 log_chart.innerHTML = s;386 387 388 389 logger.show();390 if (Ajax.prototype.queue.length > 0)391 setTimeout(function() {392 see_chart();393 }, 500);394 }395 396
Este ShareCode tiene versiones:
- God Ajax Test 1 Test 2 - Fast calls ... (08/02/2013)
- God Ajax Test 1 Test 2 - Fast calls ... (24/04/2013)
- God Ajax Test 1 Test 2 - Fast calls ... (24/04/2013)
- God Ajax Test 1 Test 2 - Fast calls ... (24/04/2013)
- God Ajax Test 1 Test 2 - Fast calls ... (24/04/2013)
- God Ajax Test 1 Test 2 - Fast calls ... (24/04/2013)
Enlace
El enlace para compartir es: