StepifyNode.js流程控制引擎
Stepify(node-stepify) 是一個(gè)簡(jiǎn)單易擴(kuò)展的Node.js流程控制引擎,采用方法鏈(methods chain)的方式定制異步任務(wù),使得Node.js工作流易于理解和維護(hù)。
目標(biāo)是將復(fù)雜的任務(wù)進(jìn)行拆分成多步完成,使得每一步的執(zhí)行過程更加透明,化繁為簡(jiǎn)。
stepify特點(diǎn)
最基本的API的就3個(gè):
step(),done(),run(),簡(jiǎn)單容易理解。精細(xì)的粒度劃分(同時(shí)支持單/多任務(wù)),執(zhí)行順序可定制化。
每一個(gè)異步操作都經(jīng)過特殊的封裝,內(nèi)部只需要關(guān)心這個(gè)異步的執(zhí)行過程。
鏈?zhǔn)剑╟hain)調(diào)用,代碼邏輯看起來比較清晰。
靈活的回調(diào)函數(shù)定制和參數(shù)傳遞。
統(tǒng)一處理單個(gè)異步操作的異常,也可根據(jù)需要單獨(dú)處理某個(gè)任務(wù)的異常。
最簡(jiǎn)單的用法
簡(jiǎn)單實(shí)現(xiàn)基于oauth2授權(quán)獲取用戶基本資料的例子:
// Authorizing based on oauth2 workflowStepify()
.step('getCode', function(appId, rUri) {
var root = this;
request.get('[authorize_uri]', function(err, res, body) {
root.done(err, JSON.parse(body).code);
});
}, [appId], [redirectUri])
.step('getToken', function(code) {
var root = this;
request.post('[token_uri]', function(err, res, body) {
root.done(err, JSON.parse(body).access_token);
});
})
.step('getInfo', function(token) {
request.get('[info_uri]?token=' + token, function(err, res, body) {
// got user info, pass it to client via http response
});
})
.run();
多個(gè)step共用一個(gè)handle、靜態(tài)參數(shù)、動(dòng)態(tài)參數(shù)傳遞的例子:
Stepify()
.step('read', __filename)
.step(function(buf) {
// buf is the buffer content of __filename
var root = this;
var writed = 'test.js';
// do more stuff with buf
// this demo just replace all spaces simply
buf = buf.toString().replace(/\s+/g, '');
fs.writeFile(writed, buf, function(err) {
// writed is the name of target file,
// it will be passed into next step as the first argument
root.done(err, writed);
});
})
.step('read')
// `read` here is a common handle stored in workflow
.read(function(p, encoding) {
fs.readFile(p, encoding || null, this.done.bind(this));
})
.run();
這里多了一個(gè)read()方法,但read方法并不是stepify內(nèi)置的方法。實(shí)際上,您可以任意“擴(kuò)展”stepify鏈!它的奧妙在于step()方法的參數(shù),詳細(xì)請(qǐng)看step調(diào)用說明。
可以看到,一個(gè)復(fù)雜的異步操作,通過stepify定制,每一步都是那么清晰可讀!
安裝
$ npm install stepify
運(yùn)行測(cè)試
$ npm install$ mocha
靈活使用
var Stepify = require('stepify');
var workflow1 = Stepify().step(fn).step(fn)...run();
// or
var workflow2 = new Stepify().step(fn).step(fn)...run();
// or
var workflow3 = Stepify().step(fn).step(fn);
// do some stuff ...
workflow3.run();
// or
var workflow4 = Stepify().task('foo').step(fn).step(fn).task('bar').step(fn).step(fn);
// do some stuff ...
workflow4.run(['foo', 'bar']);
var workflow5 = Stepify().step(fn).step(fn);
workflow5.debug = true;workflow5.error = function(err) {};
workflow5.result = function(result) {};...workflow5.run();
// more ...
注:文檔幾乎所有的例子都是采用鏈?zhǔn)秸{(diào)用,但是拆開執(zhí)行也是沒有問題的。
原理
概念:
task:完成一件復(fù)雜的事情,可以把它拆分成一系列任務(wù),這些個(gè)任務(wù)有可能它的執(zhí)行需要依賴上一個(gè)任務(wù)的完成結(jié)果,它執(zhí)行的同時(shí)也有可能可以和其他一些任務(wù)并行,串行并行相結(jié)合,這其實(shí)跟真實(shí)世界是很吻合的。
step:每一個(gè)task里邊可再細(xì)分,可以理解成“一步一步完成一個(gè)任務(wù)(Finish a task step by step)”,正所謂“一步一個(gè)腳印”是也。
stepify內(nèi)部實(shí)際上有兩個(gè)主要的類,一個(gè)是Stepify,一個(gè)是Step。
Stepify()的調(diào)用會(huì)返回一個(gè)Stepify實(shí)例,在這里稱之為workflow,用于調(diào)度所有task的執(zhí)行。
step()的調(diào)用會(huì)創(chuàng)建一個(gè)Step實(shí)例,用于完成具體的異步操作(當(dāng)然也可以是同步操作,不過意義不大),step之間使用簡(jiǎn)單的api(done方法和next方法)傳遞。
