Nodejs简单异步操作管理器


我想我每次开始写博客的第一句话都会是:好久没有写博客了,写一个吧 - -!

最近写nodejs比较多,刚开始的时候碰到的异步的操作比较少,因为想做的东西比较简单,一查api有同步的,为了省事就直接用同步的搞了,慢慢发现这不是个事呀,好好的异步特性不用,非得用同步的,真囧,并且很多东西木有同步的api的。

好!写异步的,慢慢的出现了这种代码。。。

mysql.query('xxxx').on('success', function(){
   mysql.query('xxxx').on('success', function(){
        mysql.query('xxxx').on('success', function(){
            mysql.query('xxxx').on('success', function(){
                mysql.query('xxxx').on('success', function(){
                    mysql.query('xxxx').on('success', function(){
                        //let's say fuck
                    });
                });
            });
        });
    });
});

恩,你也看到了,这样下去代码多丑,会像老太太的裹脚布一样了,于是就产生下面的异步操作管理器,小巧精致,嘿嘿,绝对够用,代码的事,用代码说话吧,直接亮代码,如码:

TODO:不够全面,比如说出错的就没有处理

/*
 *  异步管理器
 *  author : jser.me
 *
 *  使用方法:
 *     var asyncMg = require('./AsyncManager')
 *     asyncMg
 *     .push(function( next ){
 *         some_aysnc_method().on('success'{
 *            ....
 *            next()
 *         })
 *     })
 *     .push(function( next ){
 *         other_aysnc_method().on('success'{
 *            ....
 *            next()
 *         })
 *     })
 *     .push( ... )
 *     .run() //执行
 *     .on('success', function(){
 *          allThings_is_down()
 *     })
 *
 *     push方法接受数组
 */

function typeOf (obj) {
  return Object.prototype.toString.call(obj).match(/\[object ([^\]]*)\]/)[1]
}

function AsyncManager (arg) {
  this.execArrys = []
  this.push(arg)
}

// 使用系统带的继承方法
require('util').inherits(AsyncManager, require('events').EventEmitter)

// 标记成功运行的函数数目
AsyncManager.prototype.succCount = 0

// 加入
AsyncManager.prototype.push = function (arg) {
  var This = this
  if (typeOf(arg) === 'Array') {
    arg.forEach(function (v, i) {
      This.execArrys.push(v)
    })
  } else {
    This.execArrys.push(arg)
  }

  return this // 链一个
}

// 执行
AsyncManager.prototype.run = function () {
  var self = this

  if (this.succCount === this.execArrys.length) {
    // 所有函数成功执行后触发事件
    this.emit('success')
  } else {
    this.execArrys[ this.succCount ](self.run.bind(self))
  }

  this.succCount++
  return this // 链一个
}

exports = module.exports = function (arg) {
  return new AsyncManager(arg)
}

推荐文章