0.1.4 • Published 6 years ago

jzflow v0.1.4

Weekly downloads
1
License
MIT
Repository
github
Last release
6 years ago

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、执行结果

image.png

0.1.4

6 years ago

0.1.3

6 years ago

0.1.2

6 years ago

0.1.1

6 years ago

0.1.0

6 years ago

0.0.9

6 years ago

0.0.8

6 years ago

0.0.7

6 years ago

0.0.6

6 years ago

0.0.5

6 years ago

0.0.4

6 years ago

0.0.3

6 years ago

0.0.2

6 years ago

0.0.1

6 years ago