Stepify(node-stepify)是一个简单易扩展的Node.js流程控制引擎,采用方法链(methodschain)的方式定制异步任务,使得Node.js工作流易于理解和维护。
目标是将复杂的任务进行拆分成多步完成,使得每一步的执行过程更加透明,化繁为简。
stepify特点最基本的API的就3个:step(),done(),run(),简单容易理解。
精细的粒度划分(同时支持单/多任务),执行顺序可定制化。
每一个异步操作都经过特殊的封装,内部只需要关心这个异步的执行过程。
链式(chain)调用,代码逻辑看起来比较清晰。
灵活的回调函数定制和参数传递。
统一处理单个异步操作的异常,也可根据需要单独处理某个任务的异常。
最简单的用法简单实现基于oauth2授权获取用户基本资料的例子:
// 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();多个step共用一个handle、静态参数、动态参数传递的例子:
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();这里多了一个read()方法,但read方法并不是stepify内置的方法。实际上,您可以任意“扩展”stepify链!它的奥妙在于step()方法的参数,详细请看step调用说明。
可以看到,一个复杂的异步操作,通过stepify定制,每一步都是那么清晰可读!
安装$ npm install stepify运行测试$ npm install$ mocha灵活使用var Stepify = require('stepify');var workflow1 = Stepify().step(fn).step(fn)...run();// orvar workflow2 = new Stepify().step(fn).step(fn)...run();// orvar workflow3 = Stepify().step(fn).step(fn);// do some stuff ...workflow3.run();// orvar 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 ...注:文档几乎所有的例子都是采用链式调用,但是拆开执行也是没有问题的。
原理概念:
task:完成一件复杂的事情,可以把它拆分成一系列任务,这些个任务有可能它的执行需要依赖上一个任务的完成结果,它执行的同时也有可能可以和其他一些任务并行,串行并行相结合,这其实跟真实世界是很吻合的。
step:每一个task里边可再细分,可以理解成“一步一步完成一个任务(Finishataskstepbystep)”,正所谓“一步一个脚印”是也。
stepify内部实际上有两个主要的类,一个是Stepify,一个是Step。
Stepify()的调用会返回一个Stepify实例,在这里称之为workflow,用于调度所有task的执行。
step()的调用会创建一个Step实例,用于完成具体的异步操作(当然也可以是同步操作,不过意义不大),step之间使用简单的api(done方法和next方法)传递。
评论