javascript 多線程非同步隊列
首先,你得知道 jQuery.Deferred 的大致用法,然後,我們進入正題吧: 庫代碼: 複製代碼/*! * 多線程非同步隊列 * 依賴 jQuery 1.8+ (如果你用的是 1.6或1.7, 只要將源碼中的 then方法替換為pipe方法 即可) */ /** * @n {Number} 正整數, 線程數量 */function Queue (n) { n = parseInt(n || 1, 10); return (n && n > 0) ? new Queue.prototype.init(n) : null;} Queue.prototype = { init: function (n) { this.threads = []; this.taskList = []; while (n--) { this.threads.push(new this.Thread) } }, /** * @callback {Fucntion} promise對象done時的回呼函數,它的傳回值必須是一個promise對象 */ push: function (callback) { if (typeof callback !== 'function') return; var index = this.indexOfIdle(); if (index != -1) { this.threads[index].idle(callback) try { console.log('Thread-' + (index+1) + ' accept the task!') } catch (e) {} } else { this.taskList.push(callback); for (var i = 0, l = this.threads.length; i < l; i++) { (function(thread, self, id){ thread.idle(function(){ if (self.taskList.length > 0) { try { console.log('Thread-' + (id+1) + ' accept the task!') } catch (e) {} var promise = self.taskList.pop()(); // 正確的傳回值應該是一個promise對象 return promise.promise ? promise : thread.promise; } else { return thread.promise } }) })(this.threads[i], this, i); } } }, indexOfIdle: function () { var threads = this.threads, thread = null, index = -1; for (var i = 0, l = threads.length; i < l; i++) { thread = threads[i]; if (thread.promise.state() === 'resolved') { index = i; break; } } return index; }, Thread: function () { this.promise = $.Deferred().resolve().promise(); this.idle = function (callback) { this.promise = this.promise.then(callback) } }}; Queue.prototype.init.prototype = Queue.prototype;複製代碼使用樣本: 複製代碼 var queue = new Queue(3); // 建立一個具有3個線程的隊列 // task-1 queue.push(function(){ var defer = $.Deferred(); setTimeout(function(){ defer.resolve() }, 8000); return defer.promise() }) // task-2 queue.push(function(){ var defer = $.Deferred(); setTimeout(function(){ defer.resolve() }, 2000); return defer.promise() }) // task-3 queue.push(function(){ var defer = $.Deferred(); setTimeout(function(){ defer.resolve() }, 6000); return defer.promise() }) // task-4 queue.push(function(){ var defer = $.Deferred(); setTimeout(function(){ defer.resolve() }, 3000); return defer.promise() }) // task-5 queue.push(function(){ var defer = $.Deferred(); setTimeout(function(){ defer.resolve() }, 2000); return defer.promise() }) // task-6 queue.push(function(){ var defer = $.Deferred(); setTimeout(function(){ defer.resolve() }, 2000); return defer.promise() })複製代碼控制台有顯示 queue.push的 function (暫且叫它task) 最終是哪個進程處理的 執行個體化後,隊列裡的3個線程都是處於空閑狀態的將task-1分配給線程1, 這個任務耗時 8s將task-2分配給線程2, 這個任務耗時 2s將task-3分配給線程3, 這個任務耗時 6s 因為當前沒有空閑進程,隊列內部則將task-4、task-5、task-6添加到等候區 因為task-2耗時2s,進程2最先被解放,然後task-4就被分配到進程2去處理,以此類推,最後控制台顯示的進程使用方式是:1、2、3、2、2、3 這個庫的使用情境是這樣的1、如本人最近做的項目:主播在做直播,很多觀眾會給主播送禮物,這些禮物都是有js動畫特效的,頁面中最多可以同時顯示三個禮物特效 2、相互依賴的非同步請求a請求依賴b請求,b請求依賴c請求,c請求依賴。。。這個需求我們就可以使用這個庫這樣實現: 複製代碼var queue = new Queue(1); // request cqueue.push(function(){ return $.ajax(); // jq 的ajax返回的正是 promise對象}) // request bqueue.push(function(){ return $.ajax();}) // request aqueue.push(function(){ return $.ajax();})複製代碼 queue.push(callback) callback必須返回一個promise對象