public
Last active

An "async listener" concept for EventEmitters. When the listener has a callback function in its arguments list, then it is doing async work

  • Download Gist
README.md
Markdown

async-emit

Emits an event on an EventEmitter where the listener may include a callback function

An asyncEmit() function that accepts an EventEmitter, an Array of args, and a callback function. If the emitter listener function has an arity > args.length then there is an assumed callback function on the emitter, which means that it is doing some async work. We have to wait for the callbacks for any async listener functions.

It works like this:

var emitter = new EventEmitter()

// this is an async listener
emitter.on('something', function (val, done) {
  // val may be any number of input arguments
  setTimeout(function () {
    done()
  }, 1000)
})

// this is a sync listener, no callback function
emitter.on('something', function (val) {

})

asyncEmit(emitter, 'something', [ 5 ], function (err) {
  if (err) throw err
  console.log('DONE!')
})
asyncEmit.js
JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
 
/**
* An `asyncEmit()` function that accepts an EventEmitter, an Array of args, and
* a callback function. If the emitter listener function has an arity
* > args.length then there is an assumed callback function on the emitter, which
* means that it is doing some async work. We have to wait for the callbacks for
* any async listener functions.
*
* It works like this:
*
* var emitter = new EventEmitter
*
* // this is an async listener
* emitter.on('something', function (val, done) {
* // val may be any number of input arguments
* setTimeout(function () {
* done()
* }, 1000)
* })
*
* // this is a sync listener, no callback function
* emitter.on('something', function (val) {
*
* })
*
* asyncEmit(emitter, 'something', [ 5 ], function (err) {
* if (err) throw err
* console.log('DONE!')
* })
*
* From: https://gist.github.com/1811707
*/
 
module.exports = asyncEmit;
 
function asyncEmit (emitter, eventName, args, callback) {
 
if (typeof args == 'function') {
callback = args;
args = [];
}
 
var async = emitter.listeners(eventName).filter(function (func) {
return func.length > args.length;
}).length;
 
var argv = [ eventName ].concat(args);
 
// callback function
argv.push(function (err) {
if (err && !callback.called) {
callback.called = true;
callback(err);
}
--async || callback();
});
 
// no async listeners
if (async === 0) {
process.nextTick(callback);
}
 
return emitter.emit.apply(emitter, argv);
}
package.json
JSON
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
{
"name": "async-emit",
"version": "1.0.1",
"description": "Emits an event on an EventEmitter where the listener may include a callback function",
"main": "asyncEmit.js",
"repository": {
"type": "git",
"url": "git://gist.github.com/1811707.git"
},
"keywords": [
"EventEmitter",
"emit",
"async"
],
"author": "Nathan Rajlich <nathan@tootallnate.net> (http://n8.io)",
"license": "MIT"
}

Very cool! Checking the function's signature length to detect if its an async listener or not is pretty clever.

I wrote something very similar in CoffeeScript the other day and stumbled here while looking for it :)

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.