Skip to content

Instantly share code, notes, and snippets.

@wesleytodd
Last active August 29, 2015 14:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wesleytodd/057fe759f8cbeba69c05 to your computer and use it in GitHub Desktop.
Save wesleytodd/057fe759f8cbeba69c05 to your computer and use it in GitHub Desktop.
Async Control Flow

Callbacks are great

function myDataGetterThingy(done) {
  var xhr = new XMLHttpRequest();
  xhr.onreadystatechange = function() {
    if (xhr.readyStateChange === 4) {
      try {
        var res = JSON.parse(xhr.responseText);

        // Handel an error status
        if (xhr.status !== 200) {
          return done(xhr.status, res);
        }

        // Successful response
        done(null, res);
      } catch(e) {
        // JSON parse error
        done(e);
      }
    }
  };
  xhr.onerror = function() {
    done('Request failed');
  };
  xhr.open('GET', 'foo.json', true);
  xhr.send(null);
}

myDataGetterThingy(function(err, res) {
  if (err) {
      return console.error(err);
  }
  // Do some other awesome stuff with the data
});

Except when they are not

Callback Hell

Let's add a new async task and to a few things at once:

function anotherAsyncee(done) {
  // Do some stuff
  done();
}

Doing one thing after another

myDataGetterThingy(function(err, res) {
  if (err) {
    return console.error(err);
  }
  anotherAsyncee(function(err) {
    if (err) {
      return console.error(err);
    }
    console.log('Success!!!');
  });
});

Doing two things at once

var complete = 0;

function done(err, res) {
  if (err) {
    return console.error(err);
  }
  complete++;
  console.log(res);
  if (complete === 2) {
    console.log('Success!!!');
  }
}

myDataGetterThingy(done);
anotherAsyncee(done);

Why Do We Need This?

The Javascript VM is single threaded. So it can only do one thing at a time. To do two things at once Javascript needs to create other threads and then wait for them to finish.

In Node

Nodejs

Thanks to Richard Key for the diagram.

In the browser

Webkit

Thanks to Paul Irish for the diagram.

Promises Are The Future

function myDataGetterThingy() {
  return new Promise(function(resolve, reject) {
    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function() {
      if (xhr.readyStateChange === 4) {
        try {
          var res = JSON.parse(xhr.responseText);

          // Handel an error status
          if (xhr.status !== 200) {
            return reject(res);
          }

          // Successful response
          resolve(res);
        } catch(e) {
          // JSON parse error
          reject(e);
        }
      }
    };
    xhr.onerror = function() {
      reject('Request failed');
    };
    xhr.open('GET', 'foo.json', true);
    xhr.send(null);
  });
}

myDataGetterThingy().then(function(res) {
  // Do some other awesome stuff with the data
}, function(err) {
  console.error(err);
});

Juggling isn't that bad with Promises

Callback Hell

// In series
myDataGetterThingy().then(function(res) {
  return anotherAsyncee();
}).then(function(res) {
  console.log('Success!!!');
}).catch(function(err) {
  console.error(err);
});

// In parallel
Promise.all([myDataGetterThingy, anotherAsyncee]).then(function() {
  console.log('Success!!!');
}).catch(function(err) {
  console.error(err);
});

Good Resources:

Look Ma, I can do JS good!

No Training Wheels

If you are anything like me you probably only need this part:

// Series
var series = function series(fncs, done) {
  var wrap = function(i) {
    if (i == fncs.length) return done();
    fncs[i](i, function() {
      wrap(++i);
    });
  };
  wrap(0);
};

// Parallel
var parallel = function parallel(fncs, done) {
  var complete = 0;
  for (var i = 0; i < fncs.length; i++) {
    fncs[i](i, function() {
      complete++;
      if (complete == fncs.length) done();
    });
  }
};

For more of these little snippets: http://codepen.io/wesleytodd/pen/ksloC

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment