Stepify(node-stepify) 是一个简单易扩展的Node.js流程控制引擎,采用方法链(methods chain)的方式定制异步任务,使得Node.js工作流易于理解和维护。
目标是将复杂的任务进行拆分成多步完成,使得每一步的执行过程更加透明,化繁为简。
最基本的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(); // 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 ...
注:文档几乎所有的例子都是采用链式调用,但是拆开执行也是没有问题的。
概念:
task:完成一件复杂的事情,可以把它拆分成一系列任务,这些个任务有可能它的执行需要依赖上一个任务的完成结果,它执行的同时也有可能可以和其他一些任务并行,串行并行相结合,这其实跟真实世界是很吻合的。
step:每一个task里边可再细分,可以理解成“一步一步完成一个任务(Finish a task step by step)”,正所谓“一步一个脚印”是也。
stepify内部实际上有两个主要的类,一个是Stepify,一个是Step。
Stepify()
的调用会返回一个Stepify实例,在这里称之为workflow,用于调度所有task的执行。
step()
的调用会创建一个Step实例,用于完成具体的异步操作(当然也可以是同步操作,不过意义不大),step之间使用简单的api(done方法和next方法)传递。
Node.js中基本都是异步编程,我们回想下为什么初学者很容易写出深度嵌套callback的代码?因为直观啊,一眼即懂。当然实际写的时候肯定不推荐callback套callback,需要一个工具来把一个任务完整的串起来。 我们知道,在项目管理里面有一个很出名的理论,叫番茄工作法(不知道的自行google),它所做的事情是把未来一段时间要做的事情都按照时间段拆分成一个个很小的任务,然后逐个完成。 s
任何编程语言都包含的一个必要部分就是改变控制流程:if/else,for等。让我们讲述 Rust 语言中 的这部分内容。
流程控制 和Java、PHP等语言不一样,sh的流程控制不可为空,如: <?php if (isset($_GET["q"])) { search(q); } else { //do nothing } 在sh/bash里可不能这么写,如果else分支没有语句执行,就不要写这个else。 还要注意,sh里的if [ $foo -eq 0 ],这个方括号跟Java/PHP里if后面的
决策结构要求程序员指定程序要评估或测试的一个或多个条件,以及在条件被确定为true要执行的语句,以及可选的,如果条件要执行的其他语句被认定是false 。 以下是大多数编程语言中的典型决策结构的一般性 - Swift 4提供以下类型的决策声明。 单击以下链接以检查其详细信息。 Sr.No 声明和说明 1 if 语句 if语句由一个布尔表达式后跟一个或多个语句组成。 2 if...else 语句 i
Swift提供了類似 C 語言的流程控制結構,包括可以多次執行任務的for和while迴圈,基於特定條件選擇執行不同程式碼分支的if和switch語句,還有控制流程程跳轉到其他程式碼的break和continue語句。 除了 C 語言裡面傳統的 for 條件遞增(for-condition-increment)迴圈,Swift 還增加了for-in迴圈,用來更簡單地遍歷陣列(array),字典(d
算法 算法(Algorithm)是解决特定问题的步骤描述。问题的解决方案就是算法,例如,新学期开学,从家到学校的交通方式这个问题,就有很多解决方案。 一个算法,尤其是一个成熟的算法,应该具有以下五个特性: (1)确定性:算法的每一步都有确定的含义,不会出现二义性。 (2)可行性:算法的每一步都是可执行的,通过执行有限次操作来实现其功能。 (3)有穷性:一个算法必须在执行有穷步骤之后结束,且每一步都
四个假值 在 Perl 中有 4 种假值: my $false = undef; $false = ""; $false = 0; $false = "0"; 最后一个为假值是因为 "0" 在数字上下文中将变成 0,根据第三条规则, 它是假值。 后缀控制 简单的 if 或 unless 块可能看起来像这样: if ($is_frobnitz) { print "
主要内容:实例Lua 编程语言流程控制语句通过程序设定一个或多个条件语句来设定。在条件为 true 时执行指定程序代码,在条件为 false 时执行其他指定代码。 以下是典型的流程控制流程图: 控制结构的条件表达式结果可以是任何值,Lua认为false和nil为假,true和非nil为真。 要注意的是Lua中 0 为 true: 实例 --[ 0 为 true ] if ( 0 ) then print
General process(控制流程) 实现访问控制的应用程序的一般过程是: 指定用户角色: 需要在应用中定义用户角色, 例如, 可以创建匿名用户角色, 授权用户, 管理员. 定义为每个角色和模块的访问方法: 例如 你可能会允许匿名用户读取银行列表, 但是不允许做其他的事情. LoopBack models 有一套内置的方法,每个方法映射到无论是读或写 (access type)访问的类型.