Simple callbacks in sequence with ES6

Easy multiple flat asynchronous callbacks without installing extra modules.

I often find myself tempted to reach for tools like Caolan McMahon's https://github.com/caolan/async when all I have to do is simply run a few easy callbacks in sync.

Here is a simple trick to flatten sequenced callbacks without resorting to enlarging the dependency surface of your app and pulling in functionality you don't need.

Alternative to async

Forget about installing a huge package just chuck the following function in your code somewhere:

function sequence(...cbs) {  
  return new Promise((resolve, reject) => {
    cbs.push(() => resolve());
    function next() {
      const done = (err) => err ? reject(err) : next();
      cbs.length && cbs.shift()(done);
    }
    next();
  });
}

Sequence those callbacks!

Let's say we have a bunch of functions that accept a done function and run it after some operation.

const callback1 = (done) => {  
  console.log('one...');
  setTimeout(() => {
    console.log('one');
    done();
  }, 1000);
}

const callback2 = (done) => {  
  console.log('two...');
  setTimeout(() => {
    console.log('two');
    done();
  }, 1000);
}

const callback3 = (done) => {  
  console.log('three...');
  setTimeout(() => {
    console.log('three');
    done();
  }, 1000);
}

What that sequence function above can do is run each one of those callbacks one after the other and then trigger it's returned promise's resolution method.

sequence(callback1, callback2, callback3)  
  .then(() => console.log('Done!!'))
  .catch((err) => console.error(err));

It also just happens to be structured in a way where if you don't want to use the promise you can simply add a final callback as the terminating agent

sequence(callback1, callback2, callback3, (err) => {  
  if(err) {
    console.log('There was a problem!');
    return;
  }
  console.log('Done!!');
})

Rudi Yardley

Read more posts by this author.