jzflow
v0.1.4
Published
A js promise flow control library
Downloads
6
Readme
flow
一个小巧而强大的js流程框架
概述
在日常程序的开发中,你是否时常有如下的困惑:
- 1、好像又在做重复的事情?
- 2、这个项目中的流程和那个项目中的流程,明明感觉相似,但是如果要做复用又觉得少了点什么,最后又做了一次copy、paste的操作,造成后续的维护问题?
- 3、今天写好的规则,明天又要改?
- 4、需求造成了流程的变化,好像整个程序要推翻重来?
没关系,这些都可以用这个框架解决。
概念
流程是什么?
- 1、动作:基本指令,如打开某个页面;加载产品列表;将数据保存至某一张表;根据参数进行某种计算等等。
- 2、业务规则:定义动作能不能做,动作做完之后怎么办。
流程显然是动作和业务规则的组合。在理想状态下,两者应该有明确清晰的界限。但是在现实开发中,往往是两者像面条一样的混杂在一起分不清楚。 在这里,我们不去纠结原因,只寻求一种解决方案。
本框架可以:
- 1、定义app中的所有动作:给每一个动作命名,并通过名称找到动作。
- 2、定义所有业务规则:
- 3、定义流程:将动作和业务规则像搭积木一样方便的组合使用。
这里我们人为的定义:
- 动作必须为一个Promise对象,其中只能做一件事情,而流程的管控,动作一概不负责。
- 动作的参数必须为一个Object
- 业务规则为一个function,不做复杂操作,只判断动作的参数、动作的返回值,
这里又分为 异常处理规则、前置规则和后置规则
异常处理规则: 在动作发生异常之后,进行后续的处理。返回一个流程表示进入子流程处理异常,子流程处理成功继续原流程
前置规则: 判断、加工动作的参数,决定动作能不能做,返回一个流程表示动作的前置流程,做完之后继续执行原流程;返回false表示打断动作的执行,返回其他值表示接着执行流程。
后置规则: 判断、加工动作的成功返回值,决定要不要执行后续流程。返回一个流程表示动作的后续流程,本流程做完之后会继续原后续流程;返回false表示打断后续流程;返回其他值表示接着执行流程。
特性
- 1、流程和流程里面的操作步骤分离(逻辑不依赖框架)
- 2、步骤的顺序可变,每一个步骤都可以命名。可以指定从哪个步骤、以上一次执行的参数或者指定参数开始执行。
- 3、上一个步骤的结果可以传递到下一个步骤,结果的传递方式可以配置,可以指定步骤名称获取该步骤的参数和结果。
- 4、每一个步骤也可以为一个流程
- 5、在每一个步骤执行前,可以判断要不要执行,或转入其他流程
- 6、在每一个步骤执行成功之后,可判断要不要执行下一个步骤,或转入其他流程。
- 7、每一个步骤都可以针对某一种异常情况定义异常处理步骤或流程。
- 8、异常处理策略的支持,如:发生xx异常之后,重复执行某个流程、步骤三次
- 9、流程完成以后,可以收到通知。有任何异常,在任何一个步骤未处理的,也可以收到通知。
实现思路
这里优先考虑责任链模式, 引入aop。
框架命名为flow,框架应该有如下的表现形式:
流程
1、预先单独定义各个操作函数。这里定义一个标准,函数都必须返回Promise对象,函数本身不含流程控制的任何内容。
function step1(arg){
return new Promise(function(resolve,reject){
setTimeout(function(){
console.log('step1 execute',arg);
resolve({step1:'step1 complete'})
},100);
});
}
var flowCtrl = 0;
function step2(arg){
console.log('stop2 arg',arg);
return new Promise(function(resolve,reject){
setTimeout(function(){
if(flowCtrl==0){
++flowCtrl;
console.log('step2 execute');
try{
//这里模拟一个http异常
throw {code:'http'}
}catch(e){
reject(e)
}
}else{
resolve({step2:'step2 data'});
}
},100);
});
}
function step3(arg){
return new Promise(function(resolve,reject){
setTimeout(function(){
console.log('step3 arg',arg);
resolve({step3:'step3 complete'})
},100);
});
}
为了演示方便,step2在第一次的时候出错,在第二次执行的时候正确。
//如果发生了http错误,则重启流程
function step2HttpError(error){
console.log('step2Error',error);
console.log('restart progress');
flow1.restart();
}
function step2Check(arg){
console.log('step2Check',arg);
}
function step2ResultHandler(arg){
console.log('step2ResultHandler',arg);
// throw new Error();
}
2、使用流程工具整合这些操作
var flow2 = new Flow().add("step3",step3);
var flow1 = new Flow().add("step1",step1)
.add("step2",step2,{catch:{http:step2HttpError},before:step2Check,after:step2ResultHandler})
.add("step3",flow2);
这里add的第三个参数为步骤配置,catch为异常处理函数,可以指定code=某个指定值的异常的处理。before为本步骤执行前的判断函数,如果返回false,表示中止流程。after为本步骤执行成功之后的判断函数,如果返回false,表示中止流程。
4、流程工具的执行,应该也是一个Promise,这个promise成功之后返回最后一个成功执行的流程步骤(可能被before和after打断)的结果
flow1.promise({step1:'step1 data'}).then(function(result){
console.log('complete',result)
}).catch(function(error){
console.warn(error);
})
5、执行结果