Any JavaScript library that claims to help with “asynchronous control flow” must at least enable easy patterns for running asynchronous tasks in parallel, or in series.

With Atom, task parallelization is easily accomplished using .set() and .once().  (Note that this is an application of the Barrier pattern.)

var
  a = atom.create(),
  once = a.once,
  set = a.set
;

ajaxCall('/me/friends', function (friends) {
  set('friends', friends);
});

ajaxCall('/me/games', function (games) {
  set('games', games);
});

once(['games', 'friends'], function (games, friends) {
  alert(games.length + ' games and ' + friends.length +
    ' friends were fetched in parallel.');
});

And task serialization is a cinch with .chain(). Each Atom instance has an asynchronous queue of functions. With each call to .chain() you can append one or more functions to the end of the queue.

a.chain(

  // First, fetch config info from the server
  function (next) {
    ajaxCall('/config', function (config) {
      // Signal that this task is done, and pass along the config
      next(config);
    });
  },

  // Second, build the UI
  function (next, config) {
    buildUI(config, function (ui) {
      next(config, ui);
    });
  },

  // Third, wait for user to select an option
  function (next, config, ui) {
    ui.on('select', function (choice) {
      switch (choice) {
      case 1:
        // ...
      }
    });
  },

  // ...
);

For more about Atom, see: