首页 > 代码库 > 一步一步实现基于Task的Promise库(四)无参数的WorkItem
一步一步实现基于Task的Promise库(四)无参数的WorkItem
接着上一篇我直接给出代码,现在支持了new Task(), then(), all(), any() 这些不传参的调用方式。
1 (function(){ 2 var isFunction = function (target) { 3 return target instanceof Function; 4 }; 5 var isArray = function (target) { 6 return target instanceof Array; 7 }; 8 9 //自定义事件管理(代码摘抄自http://www.cnblogs.com/dolphinX/p/3254017.html) 10 var EventManager = function(){ 11 this.handlers = {}; 12 }; 13 EventManager.prototype = { 14 constructor: EventManager, 15 addHandler: function(type, handler){ 16 if(typeof this.handlers[type] == ‘undefined‘){ 17 this.handlers[type] = new Array(); 18 } 19 this.handlers[type].push(handler); 20 }, 21 removeHandler: function(type, handler){ 22 if(this.handlers[type] instanceof Array){ 23 var handlers = this.handlers[type]; 24 for(var i=0; i<handlers.length; i++){ 25 if(handler[i] == handler){ 26 handlers.splice(i, 1); 27 break; 28 } 29 } 30 } 31 }, 32 trigger: function(type, event){ 33 /* 34 if(!event.target){ 35 event.target = this; 36 } 37 */ 38 if(this.handlers[type] instanceof Array){ 39 var handlers = this.handlers[type]; 40 for(var i=0; i<handlers.length; i++){ 41 handlers[i](event); 42 } 43 } 44 } 45 }; 46 47 var WorkItem = function(arrayArgs){ 48 var _subItems = []; 49 var _checkFunc = function(args){ 50 if(isFunction(args[0])){ 51 if(args.length == 2 && isArray(args[1])){ 52 _subItems.push({‘isFunc‘: true, ‘func‘: args[0], ‘args‘: args[1]}); 53 } 54 else{ 55 _subItems.push({‘isFunc‘: true, ‘func‘: args[0], ‘args‘: args.slice(1)}); 56 } 57 return true; 58 } 59 return false; 60 }; 61 var _checkTask = function(task){ 62 if(task instanceof Task){ 63 _subItems.push({‘isFunc‘: false, ‘task‘: task}); 64 } 65 }; 66 if(!_checkFunc(arrayArgs)){ 67 for(var i=0; i<arrayArgs.length; i++){ 68 if(!_checkFunc(arrayArgs[i])){ 69 _checkTask(arrayArgs[i]); 70 } 71 } 72 } 73 var _startSubItem = function(subItemIndex, context){ 74 var subItem = _subItems[subItemIndex]; 75 if(subItem.isFunc){ 76 var workItemCxt = context.getWorkItemContext(subItemIndex); 77 subItem.func.apply(workItemCxt, subItem.args); 78 } 79 else{ 80 if(subItem.task.getStatus() == TaskStatus.finished){ 81 context.end(subItem.task.getOutput(), subItemIndex) 82 } 83 else{ 84 subItem.task.finished(function(output){ 85 context.end(output, subItemIndex); 86 }); 87 subItem.task.start(context.inputParams); 88 } 89 } 90 }; 91 92 this.condition = ""; 93 this.start = function(context){ 94 context.setItemsCount(_subItems.length); 95 for(var i=0; i<_subItems.length; i++){ 96 _startSubItem(i, context); 97 } 98 } 99 };100 //无参数的WorkItem,用于对前一个WorkItem的条件判断,例如all();101 //ConditionWorkItem和WorkItem可以看做实现了一个接口{condition:string,start:function}102 var ConditionWorkItem = function(){103 this.condition = "";104 this.start = function(context){105 context.triggerEnd();106 }107 };108 109 var Context = function(endCallback, inputParams){110 var _this = this;111 var _rawOutputParams = [];112 var _itemCount;113 //如果无需Test,_isNonTest就等于true(当调用triggerEnd方法时,就应该无需Test,直接下一个WorkItem)114 var _isNonTest = false;115 var _condition = {116 then: function(){117 _this.outputParams = _rawOutputParams[0].value;118 return true;119 },120 all: function(){121 _this.outputParams = [];122 for(var i=0; i<_itemCount; i++){123 if(_rawOutputParams[i]){124 _this.outputParams[i] = _rawOutputParams[i].value;125 }126 else{127 return false;128 }129 }130 return true;131 },132 any: function(){133 for(var i=0; i<_itemCount; i++){134 if(_rawOutputParams[i]){135 _this.outputParams = _rawOutputParams[i].value;136 return true;137 }138 }139 return false;140 }141 };142 143 this.inputParams = inputParams;144 this.outputParams = null;145 this.setItemsCount = function(itemCount){146 _itemCount = itemCount;147 };148 this.testCondition = function(key){149 //如果无需Test直接返回true,否则才用Test150 return _isNonTest || _condition[key]();151 };152 this.end = function(output, index){153 _rawOutputParams[index] = {154 value: output155 };156 if(endCallback){157 endCallback(output);158 }159 };160 this.getWorkItemContext = function(index){161 return {162 param: _this.inputParams,163 end: function(output){164 _this.end(output, index);165 }166 };167 };168 //手动触发EndCallback,(这个上下文设置成无需Test,this.outputParams就设置成this.inputParams,这样参数就可以传递到下一个WorkItem了)169 this.triggerEnd = function(){170 _isNonTest = true;171 _this.outputParams = _this.inputParams;172 if(endCallback){173 endCallback(_this.outputParams);174 }175 };176 };177 178 var TaskStatus = {179 //未开始180 pending: 0,181 //正在进行182 doing: 1,183 //已完成184 finished: 2185 };186 187 window.Task = function(){188 var _status = TaskStatus.pending;189 var _wItemQueue = [], _currentItem, _currentContext;190 var _eventManager = new EventManager();191 var _output;192 var _initWorkItem = function(args){193 var item;194 if(args.length == 0){195 item = new ConditionWorkItem();196 }197 else{198 var arrayArgs = [];199 for(var i=0; i<args.length; i++){200 arrayArgs[i] = args[i];201 }202 item = new WorkItem(arrayArgs);203 }204 _wItemQueue.push(item);205 return item;206 };207 var _setItemCondition = function(item, condition){208 if(condition){209 item.condition = condition;210 }211 };212 var _tryDoNextItem = function(output){213 var next = _getCurNextItem();214 if(next){215 if(_currentContext.testCondition(next.condition)){216 _currentItem = next;217 _doCurrentItem();218 }219 }220 else{221 _status = TaskStatus.finished;222 _output = output;223 _eventManager.trigger("finish", output);224 }225 };226 var _doCurrentItem = function(contextParam){227 if(contextParam) {228 _currentContext = new Context(_tryDoNextItem, contextParam);229 }230 else{231 if(_currentContext){232 _currentContext = new Context(_tryDoNextItem, _currentContext.outputParams);233 }234 else{235 _currentContext = new Context(_tryDoNextItem);236 }237 }238 _currentItem.start(_currentContext);239 };240 var _getCurNextItem = function(){241 var i=0;242 for(; i<_wItemQueue.length; i++){243 if(_currentItem == _wItemQueue[i]){244 break;245 }246 }247 return _wItemQueue[i + 1];248 };249 _currentItem = _initWorkItem(arguments);250 251 this.getStatus = function(){252 return _status;253 };254 this.getOutput = function(){255 return _output;256 };257 this.finished = function(callback){258 if(callback){259 _eventManager.addHandler("finish", callback);260 }261 };262 this.start = function(contextParam){263 if(_status == TaskStatus.pending){264 _status = TaskStatus.doing;265 _doCurrentItem(contextParam);266 }267 return this;268 };269 this.then = function(){270 var workItem = _initWorkItem(arguments);271 _setItemCondition(workItem, ‘then‘);272 return this;273 };274 this.all = function(){275 //这个arguments现在可能是空的了!276 var workItem = _initWorkItem(arguments);277 _setItemCondition(workItem, ‘all‘);278 return this;279 };280 this.any = function(){281 var workItem = _initWorkItem(arguments);282 _setItemCondition(workItem, ‘any‘);283 return this;284 };285 };286 })();
var task = new Task([readFile, "aa.txt"], [readFile, "bb.txt"]).all(writeBack, "cc.txt").start();
现在上面的调用形式同样可以用下面的代码代替:
1 //测试12 var taskExp_1 = new Task([readFile, "aa.txt"], [readFile, "bb.txt"]).all().then(writeBack, "cc.txt").start();3 //测试24 var taskExp_2 = new Task([readFile, "aa.txt"], [readFile, "bb.txt"]).all();5 var taskExp_3 = new Task(taskExp_2).then(writeBack, "cc.txt").start();6 //测试37 var taskExp_4 = new Task([readFile, "aa.txt"], [readFile, "bb.txt"]).all();8 var taskExp_5 = new Task().then(taskExp_4).then(writeBack, "cc.txt").start();
在下一篇,我们再来实现waitFor方法。
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。