技术笔记:waitFor和waitForAny的实现

简介: 技术笔记:waitFor和waitForAny的实现

阅读目录


waitFor和waitForAny的实现


回到目录waitFor和waitForAny的实现


在实现waitFor方法之前,我们先要搞明白下面这些问题:


1. waitFor方法的形参有限制吗?


没有!如果形参是Task类型,不应该启动Task,如果是function类型,会执行方法.所以waitFor的使用场景应该是waitFor(task1,task2),并且task1,2不知道何时启动(比如是用户点击界面按钮来启动)


2. 关于参数的传递。


1 var taskExp_0 = new Task(readFile, "123.txt");


2 var taskExp_1 = new Task(readFile, "aa.txt").start();


3 var taskExp_2 = new Task(readFile, "bb.txt");


4 var taskExp_3 = new Task(taskExp_0).waitFor(taskExp_1, taskExp_2).then(writeFile).start();


5 //taskExp_2模拟不知何时运行的Task,请在控制台运行下面代码


6 //taskExp_2.start();


上面例子中,taskExp_1,taskExp_2不接收taskExp_0的输出参数,我们希望writeFile可以通过this.Param【0】,【1】,【2】分别接收taskExp_0,taskExp_1,taskExp_2的输出参数。


明确了这样的设计后,下面是Task.js的实现细节和相关demo,有关waitFor和waitForAny的实现请看注释:


View Code


//promise


//读取文件的原始内容


var uploadFile = function (fileName) {


var _this = this;


window.setTimeout(function () {


console.log("uploadFile '" + fileName + "' complete.");


_this.end(fileName);


}, 1800);


};


//读取文件的原始内容


var readFile = function (fileName) {


_fileName = fileName || this.param;


var _this = this;


window.setTimeout(function () {


var rawContent = "xxxxxxxx (" + _fileName + ")";


console.log("read '" + _fileName + "' complete. rawContent is " + rawContent);


_this.end(rawContent);


}, 1000);


};


//请求服务器来解析原始内容,得到真正的内容


var resolveFile = function (serverUrl) {


var _this = this;


var rawContent = _this.param;


window.setTimeout(function () {


var realContent = "Greeting (" + serverUrl + ")";


console.log("resolve file complete. realContent is " + realContent);


_this.end(realContent);


}, 1500);


};


//把真正的内容写入文件


var writeFile = function (fileName) {


var _this = this;


window.setTimeout(function () {


console.log("writeBack1 param【0】 is " + _this.param【0】 + " ;param【1】 is " + _this.param【1】);


_this.end();


}, 2000);


};


var sendMail = function () {


var _this = this;


window.setTimeout(function () {


console.log("sendMail finished");


_this.end();


}, 1000);


};


(function() {


var isFunction = function (target) {


return target instanceof Function;


};


var isArray = function (target) {


return target instanceof Array;


};


//自定义事件管理(代码摘抄自)


var EventManager = function () {


this.handlers = {};


};


EventManager.prototype = {


constructor: EventManager,


addHandler: function (type, handler) {


if (typeof this.handlers【type】 == 'undefined') {


this.handlers【type】 = new Array();


}


this.handlers【type】.push(handler);


},


removeHandler: function (type, handler) {


if (this.handlers【type】 instanceof Array) {


var handlers = this.handlers【type】;


for (var i = 0; i < handlers.length; i++) {


if (handler【i】 == handler) {


handlers.splice(i, 1);


break;


}


}


}


},


trigger: function (type, event) {


/


if(!event.target){


event.target = this;


}


/


if(this.handlers【type】 instanceof Array){


var handlers = this.handlers【type】;


for(var i=0; i

handlers【i】(event);


}


}


}


};


//所有检测条件返回{result: bool, output: obj}


var Condition = {


then: function(target){


return {result: !!target【0】, output: target【0】.value};


},


all: function(target){


var output = 【】;


for(var i=0; i

if(target【i】){


output.push(target【i】.value);


}


else{


return {result: false};


}


}


return {result: true, output: output};


},


any: function(target){


for(var i=0; i

if(target【i】){


return {result: true, output: target【i】.value};


}


}


return {result: false};


}


};


//option:{


// autoStart: bool, //自动启动


// keepInputParams: bool //是否把上一步传递过来的input传递给它的下一步


//}


//finishedCallback 表示WorkItem满足条件并结束的回调


var WorkItem = function(arrayArgs, finishedCallback, option){


var _subItems = 【】;


var _rawOutputParams = 【】;


//完成WorkItem的检测条件


var _condition;


var _input;


option = option || {};


//增加一个bool类型的属性autoStart,默认值为true,表示当调用_startSubItem时是否自动执行subItem(当subItem是task时根据autoStart参数来执行task,如果subItem是方法时,不管autoStart是什么都会执行)


option.autoStart = option.autoStart !== false;


//是否把上一步传递过来的input传递给它的下一步,默认false


option.keepInput = option.keepInput === true;


var _checkFunc = function(args){


if(isFunction(args【0】)){


if(args.length == 2 && isArray(args【1】)){


_subItems.push({'isFunc': true, 'func': args【0】, 'args': args【1】});


}


else{


_subItems.push({'isFunc': true, 'func': args【0】, 'args': args.slice(1)});


}


return true;


}


return false;


};


var _checkTask = function(task){


if(task instanceof Task){


_subItems.push({'isFunc': false, 'task': task});


}


};


if(!_checkFunc(arrayArgs)){


for(var i=0; i

if(!_checkFunc(arrayArgs【i】)){


_checkTask(arrayArgs【i】);


}


}


}


_rawOutputParams.length = _subItems.length;


var _startSubItem = function(subItemIndex){


var subItem = _subItems【subItemIndex】;


if(subItem.isFunc){


var workItemCxt = _getSubItemContext(subItemIndex);


subItem.func.apply(workItemCxt, subItem.args);


}


else{


if(subItem.task.getStatus() == TaskStatus.finished){


_endSubItem(subItem.task.getOutput(), subItemIndex)


}


else{


subItem.task.finished(function(output){


_endSubItem(output, subItemIndex);


});


if(option.autoStart){


subItem.task.start(_input);


}


}


}


};


var _endSubItem = function(output, index){


_rawOutputParams【index】 = {


'value': output


};


var testResult = Condition【_condition】(_rawOutputParams);


if(testResult.result){


_onFinishedCallback(testResult.output);


}


};


var _merge = function(target, data){


if(data){


if(isArray(data)){


for(var i=0; i

target.push(data【i】);


}


}


else{


target.push(data);


}


}


};


var _onFinishedCallback = function(output){


//如果需要保留输入参数,那么需要对输入和输出参数来一个合并


if(option.keepInput){


var result = 【】;


_merge(result, _input);


_merge(result, output);


if(result.length == 0){


output = undefined;


}


else{


output = result;


}


}


finishedCallback(output)


};


var _getSubItemContext = function(index){


return {


param: _input,


end: function(output){


_endSubItem(output, index);


}


};


};


this.setCondition = function(condition){


_condition = condition;


};


this.start = function(input){


_input = input;


for(var i=0; i<_subItems.length; i++){


_startSubItem(i);


}


};


};


var ConditionWorkItem = function(finishedCallback){


this.start = function(input){


finishedCallback(input);


};


};


var TaskStatus = {


//未开始


pending: 0,


//正在进行


doing: 1,


//已完成


finished: 2


};


window.Task = function(){


var _status = TaskStatus.pending;


var _wItemQueue = 【】, _currentItem;


var _eventManager = new EventManager();


var _output;


//设置_wItemQueue队列的最后一个WorkItem的完成条件


var _setLastItemCondition = function(condition){


if(condition != null){


var last = _wItemQueue【_wItemQueue.length - 1】;


//因为ConditionWorkItem是没有setCondition方法的(它也不需要判断条件),所以有这个if


if(last.setCondition){


last.setCondition(condition);


}


}


};


var _initWorkItem = function(condition, args, option){


_setLastItemCondition(condition);


var item;


if(args.length == 0){


item = new ConditionWorkItem(_finishCallback);


}


else{


var arrayArgs = 【】;


for(var i=0; i

arrayArgs【i】 = args【i】;


}


item = new WorkItem(arrayArgs, _finishCallback, option);


}


_wItemQueue.push(item);


return item;


};


//WorkItem完成的回调


//代码效果参考:http://hnjlyzjd.com/hw/wz_24577.html

var _finishCallback = function(output){

var next = _getCurNextItem();


if(next){


//如果有下一个WorkItem,就start它


_currentItem = next;


_currentItem.start(output);


}


else{


//如果没有就通知Task结束


_status = TaskStatus.finished;


_output = output;


_eventManager.trigger("finish", output);


}


};


var _getCurNextItem = function(){


var i=0;


for(; i<_wItemQueue.length; i++){


if(_currentItem == _wItemQueue【i】){


break;


}


}


return _wItemQueue【i + 1】;


};


_currentItem = _initWorkItem(null, arguments);


this.getStatus = function(){


return _status;


};


this.getOutput = function(){


return _output;


};


this.finished = function(callback){


if(callback){


_eventManager.addHandler("finish", callback);


}


};


this.start = function(input){


if(_status == TaskStatus.pending){


_status = TaskStatus.doing;


//start的时候给最后一个WorkItem设置then条件


_setLastItemCondition("then");


_currentItem.start(input);


}


return this;


};


this.waitFor = function(){


//先初始化一个不会自启动的WorkItem,并且这个WorkItem把上一步传递过来的input传递给它的下一步


//进入这个WorkItem的条件是then,如果你想要进入条件是all,可以这样 xxxxx.all().waitFor(task1).xxxxx


_initWorkItem("then", arguments, {autoStart: false, keepInput: true});


//最后调用all()表示这个WorkItem里面的所有子Item必须都完成才能继续下一步


return this.all();


};


this.waitForAny = function(){


_initWorkItem("then", arguments, {autoStart: false, keepInput: true});


//前面和waitFor的逻辑一样,最后调用any()表示这个WorkItem里面的所有子Item完成其中一个就可以进入下一步


return this.any();


};


this.then = function(){


_initWorkItem('then', arguments);


return this;


};


this.all = function(){


_initWorkItem('all', arguments);


return this;


};


this.any = function(){


_initWorkItem('any', arguments);


return this;


};


};


})();


var taskExp_1 = new Task(readFile, "aa.txt").then(resolveFile, "/service/fileResolve.ashx?file=aa.txt");


var taskExp_2 = new Task(uploadFile, "bb.txt").then(readFile, "bb.txt").then(resolveFile, "/service/fileResolve.ashx?file=bb.txt");


var taskExp_3 = new Task(taskExp_1).waitFor(taskExp_2).then(writeFile, 【"cc.txt"】).then(sendMail).start();


//taskExp_2模拟不知何时运行的Task,请在控制台运行下面代码


//taskExp_2.start();


分类:


【10】JS


分类: Web前端


标签: Task.js


    出处:


版权信息

相关文章
|
存储 移动开发 C++
学习C++笔记425
C++ Web 编程
89 0
|
C++
学习C++笔记413
C++ Web 编程
79 0
|
存储 C++
学习C++笔记349
C++ 动态内存
66 0
|
C++
学习C++笔记339
C++ 异常处理
86 0
|
C++
学习C++笔记318
C++ 数据封装
92 0
|
C++
学习C++笔记289
C++ 继承
100 0
|
C++
学习C++笔记254
C++ 日期 & 时间
103 0
|
C++
学习C++笔记255
C++ 日期 & 时间
84 0
|
C语言 C++
学习C++笔记251
C++ 日期 & 时间
96 0
|
C++
学习C++笔记230
C++ 指针
94 0