queue-fun —— nodejs下基於Promise的隊列控制模塊。

工做告一段落,閒來無事,寫了一個在nodejs實現「半阻塞」的控制程序。javascript

一直以來,nodejs以單線程非阻塞,高併發的特性而聞名。搞這個「半阻塞」是東西,有什麼用呢?java

場景一:node

如今的web應用可有都是一個這樣的結構:git

http服務(node) > 接口(業務邏輯) > 數據庫github

不少時候,瓶頸通常出如今業務層,或者數據層。更多的多是某一個業務的處理,拉下整個系統的性能。web

當用戶或一些不懷好意的人,故意大量調用這些處理邏輯,好吧,你nodejs是非阻塞的,這一大波處理請求就一窩蜂衝到到業務層,極可能致使整個系統性能降低,或者癱瘓。數據庫

若是這個時候,node層就把這些耗資源的請求,排好隊,控制好併發,甚至分用戶排成隊,配置好不一樣身份的用戶併發量。是否是很好。npm

場景二:api

應用中,可能會有一些無需即時處理的同一類業務,處理前都須要收集一次資源,處理業務,處理後再清理一次。高消耗工做主要在收集或是清理上。promise

這個時候,咱們可將要處理的業務暫存到隊列中,當隊列數量到達一個值或是某個時間點時,咱們一次性處理完隊列中的任務。在消耗上,只作一次「收集」、「清理」的操做。

可見,若是在小型的項目中若是node方便實現相似線程池的功能,對整個項目的穩定性及工做效率是有很大貢獻的。

如今說一說我寫的這一個「半阻塞」的東西,爲何要基於Promise;

若是你用過q.js或瞭解EC6,應該對Promise有所瞭解,否則還請先了解下。

個人想法是,並不須要把整個業務的後續處理全都放到隊列中去,而只是將高消耗的那一部分放入隊列,利用Promise的異部處理機制來處理後續的操做。

在編寫代碼的時候你幾乎能夠忘記隊列的存在,可是他就在那裏默默的工做着,代碼可讀性和靈活性沒有絲毫影響。


 

queue-fun

queue-fun 是基於Promise的 運行隊列控制類。

使用場景

  • 巨量同邏輯業務平穩處理
  • 間歇性高併發系統
  • 控制單用戶佔用資源太高

隊列

queue-fun.Queue(q)

初始化隊列控制 參數q可傳

  • 無參數 隊列使用內置的實現的Promise;
  • q/ES6原生Promise 插入隊列方法: push unshift go jump返回對應的promise
實例化隊列 new queue-fun.Queue()(runMax, con)
  • runMax 並行運行隊列方法的最大個數
  • con 配置隊列 開始 結束 事件,運行單元的 成功,失敗 事件及配置執行單元出錯的 重試 機制。
var queue = new queue-fun.Queue()(100,{ "event_succ":function(){} //成功 ,"event_err":function(){} //失敗 ,"event_begin":function(){} //隊列開始 ,"event_end":function(){} //隊列完成 ,"event_add":function(){} //有執行項添加進執行單元后執行,注意go及jump不會觸發 ,"retryON":0 //隊列單元出錯重試次數 ,"retryType":0 //重試模式true/false(優先/擱置)執行 })`

API

queue.push(promisefun, args[]con)

向隊列中尾部添加運行單元 fun: promise function args: 傳入的參數 con 默認值

{
    'event_succ':null //通常沒用,某些狀況下,可能比then要方便 ,'event_err':null //通常沒用,某些狀況下,可能比then要方便 ,'Queue_event':true //默認會執行隊列定義的回調 }
queue.unshift(promisefun, args[]con) 同push 向隊列中頭部添加運行單元
queue.go(promisefun, args[]con) 同push,添加後會啓動隊列.
queue.jump(promisefun, args[]con) 同unshift,添加後啓動隊列.
setMax(newMax)

修改並行數

queue.start()

啓動隊列

queue.stop()

暫停隊列

queue.clear()

清空隊列

demo

var queuefun = require('queue-fun'); //引入 //初始化Promise異步隊列類 var Queue = queuefun.Queue(); //實列化最大併發爲2的運行隊列 var queue1 = new Queue(2,{ "event_succ":function(data){console.log('queue-succ:',data)} //成功 ,"event_err":function(err){console.log('queue-succ:',data)} //失敗 }); var q = queuefun.Q; //模塊中簡單實現了Q的基本功能,能夠一試, //定義一個Promise風格的異步方法 function testfun(i){ var deferred = q.defer(); setTimeout(function(){ if(i\ && i % 3 == 0){ deferred.reject(new Error("err " + i)) }else{ deferred.resolve(i) } },(Math.random() * 2000)>>0) return deferred.promise; } //向隊列添加運行單元 queue1.push(testfun,[1]) //添加運行項 queue1.go(testfun,[2]) //添加並自動啓動隊列 queue1.go(testfun,[3],{Queue_event:0}) //添加不會觸發隊列 回調的運行項. queue1.go(testfun,[4]).then( function(data){console.log('done-succ:',data)}, function(err){console.log('done-err:',err)} ) queue1.go(testfun,[5],{ event_succ:function(data){console.log('conf-succ:',data)}, event_err:function(err){console.log('conf-err:',err)} })

關於內置Promise實現類queuefun.Q

實現了Promises/A+規範及done,spread,fail;
API模仿Q;
模擬實現了 q.defer,q.Promise,q.all,q.any,q.nfcall,q.nfapply,q.denodeify 等函數.

.toPromis(obj).then()

若是你習慣了.then風格寫代碼,你能夠嘗試用toPromis將普通函數/語句包裝一下,讓他能夠得到then方法,及捕獲錯誤。

var add = function(a,b){return a+b;} q.toPromis(function(){return add(a+b)}) .then(console.log,console.error)

待完善

  • 集羣支持
  • 內存溢出隱患處理
  • 其它Promise實現類的支持

安裝:npm install quque-fun

github: https://github.com/cnwhy/queue-fun

相關文章
相關標籤/搜索