Joins JavaScript's asynchronous calls together similar to how `pthread_join` works for threads.
JavaScript
Switch branches/tags
Nothing to show
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
LICENSE added license and wget instructions Jan 12, 2014
README.md Fix typo Jan 13, 2014
bower.json initial commit of 3.0.0 Jan 12, 2014
join.js
package.json
test.js initialize length to 0 Jan 12, 2014

README.md

Join

Joins any number of asynchronous calls together - similar to how pthread_join works for C threads and when() works for Q-style promises.

It's basically a callback counter that lets you know when everything is done.

Installation

Node.JS (Server):

npm install join

Browser:

You can install from bower:

bower install join

Or download the raw file from https://raw.github.com/FuturesJS/join/master/join.js:

wget https://raw.github.com/FuturesJS/join/master/join.js

Browser Usage

<script src="join.js"></script>
;(function () {
  'use strict';

  var join = window.Join.create()
    ;

  // Use `join.add()` in place of a callback function
  setTimeout(join.add(), 500, 'I', 'really');
  setTimeout(join.add(), 700, 'really', 'LOVE');
  setTimeout(join.add(), 200, 'JavaScript');

  // Use `join.notify()` for incremental updates
  join.notify(function (i, args) {
    console.log(
      'Callback #' + (i + 1) 
    + ' of ' + join.length 
    + ' completed', args
    );
  });

  // Use `join.then(cb)` to fire `cb` when all of the `join.add()` callbacks have been called.
  join.then(function (i, love, js) {
    console.log('All of the timeouts have completed');
    console.log(i, love, js);
  });
}());

Node.js Usage

'use strict';

var request = require('request')
  , Join = require('join').Join
  , join = Join.create()
  ;

// Use `join.add()` in place of a callback function
request.get('https://www.google.com', join.add());
request.get('http://www.yahoo.com', join.add());
request.get('https://www.bing.com', join.add());

// Use `join.notify()` for incremental updates
join.notify(function (i, args) {
  console.log(
    'Callback #' + (i + 1) 
  + ' of ' + join.length 
  + ' completed', args
  );
});

// Use `join.then(cb)` to fire `cb` when all of the `join.add()` callbacks have been called.
join.then(function (googleArgs, yahooArgs, bingArgs) {
  console.log('All of the requests have completed');
  console.log(googleArgs[2]);
  console.log(yahooArgs[2]);
  console.log(bingArgs[2]);
});

API

Join

  • join = Join.create(defaultContext=null) - create a Join that will count callbacks
  • join.add() - creates a joinable callback that you can throw around
  • join.notify(progressCallback, context=null)
  • join.then(finalCallback, context=null)
    • Fires finalCallback when all joined callbacks have completed
    • Must be called after the last add()
  • join.length - the number of times join.add() has been called

Potential Gotchas

Order matters

The arguments to join.then(cb) are in the order that the join.add() were called.

  callbackA = join.add();
  callbackB = join.add();

  doAsyncStuff(callbackB);
  doAsyncStuff(callbackA);

  join.then(function (callbackAArgs, callbackBArgs) {
    console.log(callbackAArgs, callbackBArgs);
  });

Callback within a callback

If you handle the join callback inside of another callback then you'll need to place the join callback in the parent scope.

Fails:

  request.get('http://www.yahoo.com', join.add());
  setTimeout(function () {
    request.get('https://www.bing.com', join.add());
  }, 100);

  join.then(function () {
    console.log('all completed');
  });

Works as expected:

  request.get('http://www.yahoo.com', join.add());
  bingCallback = join.add()
  setTimeout(function () {
    request.get('https://www.bing.com', bingCallback);
  }, 100);

Losing thisness

Fails:

  // `doStuff` loses the `this` binding to `myObject`
  join.then(myObject.doStuff);

Works as expected:

  // `doStuff` retains the `this` binding
  join.then(myObject.doStuff, myObject);

Also works as expected:

  // `doStuff` retains the `this` binding
  join.then(function (argsA, argsB, argsC) {
    myObject.doStuff(argsA, argsB, argsC);
  });