论坛首页 Web前端技术论坛

Javascript工作流引擎代码及实例

浏览 9130 次
精华帖 (2) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2009-03-06   最后修改:2009-04-21
最近在学习jBPM和Javascript,所以按照一些相关概念自己写了下面的200行代码的“工作流引擎”,工作流管理系统包含了流程定义,引擎,及应用系统三个主要部分,下面的代码实现了流程的分支合并,目前只支持一种环节上的迁移。下载html附件双击就可以跑起来。
/*/////////流程定义///////////
		  start
		   / \
		  1   \
		 / \   \
		4   5  2
		 \ /  / 
		   \ / 
		    3
		    |
		   end 
测试流程如上图所示
/////////////////////////////*/
var workflowDef = {
	start:{
		fn:"begin", //对应处理方法可以在内部定义,也可以在外部定义
		next:["task1","task2"]
	},
	end:"end",
	tasks:[{
		id:"task1",
		fn:function(){
			alert("执行任务一");
		},
		before:function(){
			alert("执行任务一前");
		},
		after:function(){
			alert("执行任务一后");
		},
		next:["task4","task5"]
	},{
		id:"task2",
		fn:function(){
			alert("执行任务二");
		},
		before:function(){
			alert("执行任务二前");
		},
		after:function(){
			alert("执行任务二后");
		},
		next:["task3"]
	},{
		id:"task3",
		fn:function(){
			alert("执行任务三");
		},
		before:function(){
			alert("执行任务三前");
		},
		after:function(){
			alert("执行任务三后");
		},
		//定义合并的数量
		merge: 3,
		next:"EOWF"
	},{
		id:"task4",
		fn:function(){
			alert("执行任务四");
		},
		before:function(){
			alert("执行任务四前");
		},
		after:function(){
			alert("执行任务四后");
		},
		next:["task3"]
	},{
		id:"task5",
		fn:function(){
			alert("执行任务五");
		},
		before:function(){
			alert("执行任务五前");
		},
		after:function(){
			alert("执行任务五后");
		},
		next:["task3"]
	}]
}

//////////定义引擎////////////
Yi = {};
Yi.Utils = {};

Yi.Utils.execute = function(o){
	if(typeof o != 'function')
		eval(o)();
	else
		o();
}
//工作流类
Yi.Workflow = function(workflowDef){
	this.def = workflowDef;
	this.tasks = this.def.tasks;
}
//public按照环节id查找查找
Yi.Workflow.prototype.findTask = function(taskId){
	for(var i=0;i<this.tasks.length;i++){
		if(this.tasks[i].id == taskId)
			return this.tasks[i];
	}
}
//public启动工作流
Yi.Workflow.prototype.start = function(){
	this.currentTasks = [];
	Yi.Utils.execute(this.def.start.fn);
	for(var i=0;i<this.def.start.next.length;i++){
		this.currentTasks[i] = this.findTask(this.def.start.next[i]);
		Yi.Utils.execute(this.currentTasks[i].before);
	}
}
//private
Yi.Workflow.prototype.findCurrentTaskById = function(taskId){
	for(var i=0;i<this.currentTasks.length;i++){
		if(this.currentTasks[i].id == taskId)
			return this.currentTasks[i];
	}
	return null;
}
//private
Yi.Workflow.prototype.removeFromCurrentTasks = function(task){
	var temp = [];
	for(var i=0;i<this.currentTasks.length;i++){
		if(!(this.currentTasks[i] == task))
			temp.push(this.currentTasks[i]); 
	}
	this.currentTasks = temp;
	temp = null;
}
//public触发当前环节
Yi.Workflow.prototype.signal = function(taskId){
	//只处理当前活动环节
	var task = this.findCurrentTaskById(taskId);
	if(task == null){
		alert("工作流未流转到此环节!");
		return;
	}
	//对于合并的处理
	if(task.merge != undefined){
		if(task.merge != 0){
			alert("工作流流转条件不充分!");
			return;
		}else{
			Yi.Utils.execute(task.before);
		}	
	}
	//触发当前环节
	Yi.Utils.execute(task.fn);
	//触发后动作
	Yi.Utils.execute(task.after);
	//下一步如果工作流结束
	if(task.next === "EOWF"){
		Yi.Utils.execute(this.def.end);
		delete this.currentTasks;
		return;
	}
	//遍历下一步环节
	this.removeFromCurrentTasks(task);
	for(var i=0;i<task.next.length;i++){
		var tempTask = this.findTask(task.next[i]);
		if(!tempTask.inCurrentTasks)
			this.currentTasks.push(tempTask);
		if(tempTask.merge != undefined){
			tempTask.merge--;
			tempTask.inCurrentTasks = true;
		}
		else
			Yi.Utils.execute(tempTask.before);
	}
}
//public获取当前的活动环节
Yi.Workflow.prototype.getCurrentTasks = function(){
	return this.currentTasks;
}
//public获取流程定义
Yi.Workflow.prototype.getDef = function(){
	return this.def;
}

////////应用系统///////////////
var wf = new Yi.Workflow(workflowDef);
alert("启动工作流");
wf.start();
alert("尝试手工执行任务3,返回工作流没有流转到这里");
wf.signal("task3");
alert("分支开始");
alert("手工执行任务1");
wf.signal("task1");
alert("手工执行任务2");
wf.signal("task2");
alert("手工执行任务4");
wf.signal("task4");
alert("手工执行任务5");
wf.signal("task5");
alert("手工执行任务3");
wf.signal("task3");
function begin(){
	alert("流程开始,该函数在外部定义");
}
function end(){
	alert("流程结束");
}
   发表时间:2009-03-06  
工作流定义采用了json形式,其流程图如下:
0 请登录后投票
   发表时间:2009-03-11  
ccmv 写道
比较有创意啊

谢谢,现在主要是找不到这个东西的应用场景,所以只能当个玩具练练手了,不然准备扩展一下,做一个jpdl或者xpdl转json的工具了
0 请登录后投票
   发表时间:2009-03-24  
不知道你这个主要用于做什么的?

我还以为是通过js来实现流程的绘制呢.如果用js来实现流程控制,感觉意义不大
0 请登录后投票
   发表时间:2009-03-24  
hanjs 写道
不知道你这个主要用于做什么的?

我还以为是通过js来实现流程的绘制呢.如果用js来实现流程控制,感觉意义不大


想象一个场景,你有一些游离的页面,之间没有确定的逻辑关系,或者每次确定的逻辑关系都不同,但是针对每个页面来说,为其服务的后台处理是一定的,那么表单的流转就需要一个引擎去控制了,可以通过cookies来持久表单流转的状态,这样每次用户登陆后就可以找到自己上次处理的表单,并按照既定的流程走下去。

具体例子:
对于用户1:
页面
A->B->C & D -> E
对于用户2
A->B->E
于是就不必在B处理完后去判断是返回C和D还是返回E
1 请登录后投票
   发表时间:2009-04-15  
这个思路有点意思 现在js前端应用不少 一定有应用场景的
如果结合AJAX 那么在一个稍微复杂(流程方面)一点的前端应用中就能派上用场了
0 请登录后投票
   发表时间:2009-04-16  
不错的想法,在相应的task的function中去调用后台的logic,应该可以实现一个简单的flow
0 请登录后投票
   发表时间:2009-04-17  
我也想找一些画图的工具,
0 请登录后投票
论坛首页 Web前端技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics