Frage

In Mixu's Node.js book, there is a very awesome section about control flow. The following pattern allows you to chain async requests in series to make sure an event has completed before calling the next one. I'd like to modify this so that the response from one async request can then passed as an argument to the next.

Any ideas?

http://book.mixu.net/node/ch7.html http://jsfiddle.net/B7xGn/

function series(callbacks, last) {
  var results = [];
  function next() {
    var callback = callbacks.shift();
    if(callback) {
      callback(function() {
        results.push(Array.prototype.slice.call(arguments));
        next();
      });
    } else {
      last(results);
    }
  }
  next();
}
// Example task
function async(arg, callback) {
  var delay = Math.floor(Math.random() * 5 + 1) * 100; // random ms
  console.log('async with \''+arg+'\', return in '+delay+' ms');
  setTimeout(function() { callback(arg * 2); }, delay);
}
function final(results) { console.log('Done', results); }

series([
  function(next) { async(1, next); },
  function(next) { async(2, next); },
  function(next) { async(3, next); },
  function(next) { async(4, next); },
  function(next) { async(5, next); },
  function(next) { async(6, next); }
], final);
War es hilfreich?

Lösung

You can change the next function signature so that you can pass it a result. Here's how you could do it.

function series(callbacks, last) {
  var results = [];
  function next(result) {
    var callback = callbacks.shift();
    if(callback) {
      callback(function(result) {
        results.push(Array.prototype.slice.call(arguments));
        next(result);
      }, result);
    } else {
      last(results);
    }
  }
  next();
}
// Example task
function async(arg, callback) {
  var delay = Math.floor(Math.random() * 5 + 1) * 100; // random ms
  console.log('async with \''+arg+'\', return in '+delay+' ms');
  setTimeout(function() { callback(arg * 2); }, delay);
}

function final(results) { console.log('Done', results); }

series([
  function(next) { async(1, next); },
  function(next, result) { console.log('result: ', result); async(2, next); },
  function(next, result) { console.log('result: ', result); async(3, next); },
  function(next, result) { console.log('result: ', result); async(4, next); },
  function(next, result) { console.log('result: ', result); async(5, next); },
  function(next, result) { console.log('result: ', result); async(6, next); }
], final);

EDIT:

To be able to pass multiple results, you could simply change the series function to:

function series(callbacks, last) {
  var results = [];
  function next() {
    var callback = callbacks.shift(), args;
    if(callback) {
      callback.apply(this, (args = [
        function() {
          results.push(Array.prototype.slice.call(arguments));
          next.apply(this, arguments);
        }
      ]).concat.apply(args, arguments));
    } else {
      last(results);
    }
  }
  next();
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top