Tuan-Anh Tran

Fuck callbacks! Let's use generators

Posted on January 18, 2015  •  2 minutes  • 314 words

Let’s write a simple function hello that return a string when called.

var hello = function () { return 'Hello ' + name; }

Now convert it into a generator. Call hello() this time will return you an Object instead: the generator.

var hello = function *() { return 'Hello ' + name; }

Let’s consider the following snippet.

var hello = function *() {
  yield 'Stopped here!';
  return 'Hello ' + name;
}

var generator = hello('Clark Kent');
console.log(generator.next()); // {value: 'Stopped here', done: false}
console.log(generator.next()); // {value: 'Hello Clark Kent', done: true}

So what good can generators do for me? Generators can help eliminiating callbacks. Using callback for 1 or maybe 2 levels is fine. However, imagine if you have to use callbacks for 3 levels or more like the example below. URGH!!

func_1(arg, function(err, result) {
  if (err) { .... }
  else {
    func_2(result, function(err, result2) {
      if (err) { ... }
      else {
        func_3(result2, function(err, result3) {
          if (err) { ... }
          else {
            // LOST IN LIMBO !!!
          }
        });
      }
    });
  }
});

Take an example: consider a scenario where you have to establish connection to a bunch of database servers at application startup. With generators, you can do something like this:

var init_all_connections = function *() {
  var result;
  result = yield init_connection(conn_str1);
  result = yield init_connection(conn_str2);
  result = yield init_connection(conn_str3);
  // ...

}

For the sake of conveniency, you can write a function to execute the generator until done is true, throw if an error occurs. So the whole thing looks as simple as this:

var init_all_connections = function *() {
  var result;
  result = yield init_connection(conn_str1);
  result = yield init_connection(conn_str2);
  result = yield init_connection(conn_str3);
  // ...

}
// execute
execute_generator(init_all_connections());

Look how the code is cleanly organized and so much readable compare with the callback hell above. Ain’t you glad you read this now ;)

Follow me

Here's where I hang out in social media