nodejs eventproxy

这个世界上不存在所谓回调函数深度嵌套的问题

Posted on August 24, 2014
  • 这个世界上不存在所谓回调函数深度嵌套的问题。 —— Jackson Tian
  • 世界上本没有嵌套回调,写得人多了,也便有了}}}}}}}}}}}}。 —— fengmk2

  • bad: 串行, 深度嵌套

    var render = function (template, data) {
      _.template(template, data);
    };
    $.get("template", function (template) {
      // something
      $.get("data", function (data) {
        // something
        $.get("l10n", function (l10n) {
          // something
          render(template, data, l10n);
        });
      });
    });
    
  • good: 并行, 无嵌套

    var ep = EventProxy.create("template", "data", "l10n", function (template, data, l10n) {
      _.template(template, data, l10n);
    });
    
    $.get("template", function (template) {
      // something
      ep.emit("template", template);
    });
    $.get("data", function (data) {
      // something
      ep.emit("data", data);
    });
    $.get("l10n", function (l10n) {
      // something
      ep.emit("l10n", l10n);
    });
    

API

  • all 多类型异步协作(单次)

    var EventProxy = require('eventproxy');
    var ep = new EventProxy();
    
    ep.all('event1', 'event2', function (data1, data2) {
      console.log(data1);
      console.log(data2);
    });
    
    ep.emit('event1', '1'); //第一次触发有效
    ep.emit('event1', '2'); //无效
    ep.emit('event2', '3');
    => 1
    => 3
    //类似once, 用all添加的事件, 只会被触发一次
    ep.emit('event1', '4');
    ep.emit('event2', '5');
    => 无输出
    

    all 等价于 EventProxy.create('event1', 'event2', function (data1, data2) {...

  • tail 持续型多类型异步协作

      var EventProxy = require('eventproxy');
      var ep = new EventProxy();
    
      ep.tail('event1', 'event2', function (data1, data2) {
        console.log(data1);
        console.log(data2);
      });
    
      ep.emit('event1', '1'); //第一次的数据会被覆盖
      ep.emit('event1', '2'); //有效, tail会用最新的数据
      ep.emit('event2', '3');
      => 2
      => 3
      //类似on, 用tail添加的事件, 会用最新的数据, 多次触发
      ep.emit('event1', '4');
      ep.emit('event2', '5');
      => 4
      => 5
    
  • after 重复单类型异步协作

      var EventProxy = require('eventproxy');
      var ep = new EventProxy();
    
      ep.after('event', 10, function(datas) {
        //datas 是按序累积的事件返回数据数组
      });
    
  • 友好的Error handling

    exports.getContent = function (callback) {
     var ep = new EventProxy();
      ep.all('tpl', 'data', function (tpl, data) {
        // 成功回调
        callback(null, {
          template: tpl,
          data: data
        });
      });
      // 添加error handler
      ep.fail(callback);
    
      fs.readFile('template.tpl', 'utf-8', ep.done('tpl'));
      db.get('some sql', ep.done('data'));
    };
    
  • fail

    ep.fail(callback);
    // 由于参数位相同,它实际是
    ep.fail(function (err) {
      callback(err);
    });
    
    // 等价于
    ep.bind('error', function (err) {
      // 卸载掉所有handler
      ep.unbind();
      // 异常回调
      callback(err);
    });
    
  • done 其实是个偏函数, 当有error, 自动触发error事件, 否则触发对应完成事件

    ep.done('tpl'); 
    // 等价于
    function (err, content) {
      if (err) {
        // 一旦发生异常,一律交给error事件的handler处理
        return ep.emit('error', err);
      }
      ep.emit('tpl', content);
    }
    

    上例中接受事件名的done, 没有预处理数据的能力, 如需预处理数据, 可以传递函数给done

参考资料