异步工作流控制-condCall

144 阅读1分钟

在JavaScript编程中,异步操作一直是一个问题,回调是一种深层次的嵌套处理方式,我们也可以把嵌套处理转为直线处理以简化异步处理。有过prolog和erlang编程了解的同学可能对模式匹配有深刻的印象,我们也可以借鉴此种思想处理异步问题-条件执行。

此方案描述如下:

  1. 创建一个依赖状态state
  2. 把有异步依赖关系的操作抽象成,条件->执行
  3. 当条件不满足时将操作缓存到任务列表
  4. 当条件满足时立即执行,并重新执行任务列表中符合条件的操作 函数实现如下:
var condCall=function (state) {
    var list = [];
    var fn=function(cond,handle) {
        if (cond(state)) {
            handle(state, function () {
                _.remove(list, function (o) { return o.cond(state); })
          .forEach(function (o) { fn(o.cond, o.handle) });
            });
        } else {
            list.push({ cond: cond, handle: handle });
        }
    }
    return fn;
}

注:_为lodash库函数
我们测试一下此函数应用
顺序执行(first,second,third依次执行,3个函数可以以任意顺序排列)

var f=condCall({step:1});
f(
    function(state){return state.step==2;},
    function(state,cb){console.log('second');state.step=3;cb();}
);
f(
    function(state){return state.step==1;},
    function(state,cb){console.log('first');state.step=2;cb();}
);
f(
    function(state){return state.step==3;},
    function(state,cb){console.log('third');cb();}
);

输出:

first
second
third

并行执行(等待fisrt和second执行完后再执行third,3个函数可以以任意顺序排列)

var f=condCall({first:false,second:false});
f(
    function(state){return state.first&&state.second;},
    function(state,cb){console.log('third');cb();}
);
f(
    function(state){return !state.first;},
    function(state,cb){console.log('first');state.first=true;cb();}
);
f(
    function(state){return !state.second;},
    function(state,cb){console.log('second');state.second=true;cb();}
);

输出:

first
second
third