• 一步一步实现基于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,否则才用Test
    150             return _isNonTest || _condition[key]();
    151         };
    152         this.end = function(output, index){
    153             _rawOutputParams[index] = {
    154                 value: output
    155             };
    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: 2
    185     };
    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 })();
    View Code
    var task = new Task([readFile, "aa.txt"], [readFile, "bb.txt"]).all(writeBack, "cc.txt").start();

    现在上面的调用形式同样可以用下面的代码代替:

    1 //测试1
    2 var taskExp_1 = new Task([readFile, "aa.txt"], [readFile, "bb.txt"]).all().then(writeBack, "cc.txt").start();
    3 //测试2
    4 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 //测试3
    7 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方法。

  • 相关阅读:
    Spring源码阅读BeanFactory体系结构分析 coder
    Spring源码阅读IoC容器解析 coder
    Spring源码阅读ApplicationContext体系结构分析 coder
    【学习笔记】卷积神经网络 coder
    Spring源码阅读环境搭建 coder
    【学习笔记】分布式Tensorflow coder
    【spring实战第五版遇到的坑】3.1中的例子报错 coder
    阿里云服务器磁盘空间不足解决办法
    Tomcat配置https SSL证书
    mybatis:Creating a new SqlSession Closing non transactional SqlSession
  • 原文地址:https://www.cnblogs.com/lihao123/p/3869874.html
Copyright © 2020-2023  润新知