Eventproxy控制并发

用js写过异步的同学应该知道(很尴尬,我没写过),如果你要并发异步获取两三个地址的数据,并且要在获取到数据之后,对这些数据一起进行利用的话,常见的写法是自己维护一个计数器。

先定义一个var count=0,然后每次抓取成功以后,就count++。如果你是要抓取三个源的数据,由于你根本不知道这些异步操作到底谁先完成,那么每次当抓取成功的时候,就判断一下count===3。当值为真时,使用另一个函数继续完成操作。

而 eventproxy 就起到了这个计数器的作用,它来帮你管理到底这些异步操作是否完成,完成之后,它会自动调用你提供的处理函数,并将抓取到的数据当参数传过来。

假设我们不使用 eventproxy 也不使用计数器时,抓取三个源的写法是这样的:

//参考jquery的$.get方法
$.get("http://data1_source",function(data1){
  //something
  $.get("http://data2_source",function(data2){
    //something
    $.get("http://data3_source".function(data3){
        //something
        var html = fuck(data1,data2,data3);
        render(html);
    });
  });
});

上述的代码大家都写过吧。先获取 data1,获取完成之后获取 data2,然后再获取 data3,然后 fuck 它们,进行输出。

但大家应该也想到了,其实这三个源的数据,是可以并行去获取的,data2 的获取并不依赖 data1 的完成,data3 同理也不依赖 data2。

于是我们用计数器来写,会写成这样:

(function(){
    var count = 0;
    var result = {};
    $.get("http://data1_source",function(data){
      result.data1 = data;
      count++;
      handle();
    });
    $.get("http://data2_source",function(data){
      result.data2 = data;
      count++;
      handle();
    });
    $.get("http://data3_source",function(data){
      result.data3 = data;
      count++;
      handle();
    });
    function handle(){
      if(count === 3){
        var html = fuck(result.data1,result.data2,result.data3);
        render(html);
      }
    }
})();

是不是很丑?…

如果我们用 eventproxy,写出来是这样的:

var ep = new eventproxy();
ep.all('data1_event','data2_event','data3_event',function(data1,data2,data3){
  var html = fuck(data1,data2,data3);
  render(html);
});

$.get('http://data1_source',function(data){
    ep.emit('data1_event',data);
});

$.get('http://data2_source',function(data){
    ep.emit('data2_event',data);
});

$.get('http://data3_source',function(data){
    ep.emit('data3_event',data);
});

好看多了是吧,也就是个高等计数器嘛。

ep.all('data1_event', 'data2_event', 'data3_event', function (data1, data2, data3) {});

这一句,监听了三个事件,分别是 data1_event, data2_event, data3_event,每次当一个源的数据抓取完成时,就通过 ep.emit() 来告诉 ep 自己,某某事件已经完成了。

当三个事件未同时完成时,ep.emit() 调用之后不会做任何事;当三个事件都完成的时候,就会调用末尾的那个回调函数,来对它们进行统一处理。

eventproxy 提供了不少其他场景所需的 API,但最最常用的用法就是以上的这种,即:

先 var ep = new eventproxy(); 得到一个 eventproxy 实例。
告诉它你要监听哪些事件,并给它一个回调函数。ep.all(‘event1’, ‘event2’, function (result1, result2) {})。
在适当的时候 ep.emit(‘event_name’, eventData)。

转载自:https://github.com/alsotang/node-lessons/tree/master/lesson4
ps:更多node.js的基础知识可以参考alsotang的《Node.js包教不包会》:https://cnodejs.org/topic/5433d5e4e737cbe96dcef312