/** * @provides javelin-router * @requires javelin-install * javelin-util * @javelin */ /** * Route requests. Primarily, this class provides a quality-of-service * priority queue so large numbers of background loading tasks don't block * interactive requests. */ JX.install('Router', { construct: function() { this._queue = []; }, events: ['queue', 'start', 'done'], members: { _queue: null, _active: 0, _limit: 5, queue: function(routable) { this._queue.push(routable); this.invoke('queue', routable); this._update(); }, getRoutableByKey: function(key) { for (var ii = 0; ii < this._queue.length; ii++) { if (this._queue[ii].getKey() == key) { return this._queue[ii]; } } return null; }, /** * Start new requests if we have slots free for them. */ _update: function() { var active = this._active; var limit = this._limit; if (active >= limit) { // If we're already at the request limit, we can't add any more // requests. return; } // If we only have one free slot, we reserve it for a request with // at least priority 1000. var minimum; if ((active + 1) == limit) { minimum = 1000; } else { minimum = 0; } var idx = this._getNextRoutable(minimum); if (idx === null) { return; } var routable = this._queue[idx]; this._queue.splice(idx, 1); routable.listen('done', JX.bind(this, this._done, routable)); this._active++; routable.start(); this.invoke('start', routable); this._update(); }, _done: function(routable) { this._active--; this.invoke('done', routable); this._update(); }, _getNextRoutable: function(minimum) { var best = (minimum - 1); var routable = null; for (var ii = 0; ii < this._queue.length; ii++) { var priority = this._queue[ii].getPriority(); if (priority > best) { best = priority; routable = ii; } } return routable; } }, statics: { _instance: null, getInstance: function() { if (!JX.Router._instance) { JX.Router._instance = new JX.Router(); } return JX.Router._instance; } } });