1

I want to process a series of commands step by step via serial line in nodejs by using Q promises.

var cmdArr = ['cmd1', 'cmd2','cmd3'];

I am not sure how to build this. I thought about something like this but it did not work:

Q().then(function() {
  cmdArr.forEach(command) {
     //here to initialize the promise??
  }
});

Important is to keep the sequence and are able to use Q.delay in between each step.

solick
  • 2,325
  • 3
  • 17
  • 29
  • What do you mean "commands"? – stdob-- Nov 12 '15 at 21:09
  • Possible duplicate of [Resolve promises one after another (i.e. in sequence)?](http://stackoverflow.com/questions/24586110/resolve-promises-one-after-another-i-e-in-sequence) – Bergi Nov 12 '15 at 21:31

2 Answers2

1

Assuming that the commands you want to perform are some sort of async function call:

var Q = require('q');

// This is the function you want to perform. For example purposes, all this
// does is use `setTimeout` to fake an async operation that takes some time.
function asyncOperation(input, cb) {
  setTimeout(function() {
    cb();
  }, 250);
};

function performCommand(command) {
  console.log('performing command', command);
  // Here the async function is called with an argument (`command`),
  // and once it's done, an extra delay is added (this could be optional
  // depending on the command that is executed).
  return Q.nfcall(asyncOperation, command).delay(1000);
}

// Set up a sequential promise chain, where a command is executed
// only when the previous has finished.
var chain = Q();
[ 'cmd1', 'cmd2', 'cmd3' ].forEach(function(step) {
  chain = chain.then(performCommand.bind(null, step));
});

// At this point, all commands have been executed.
chain.then(function() {
  console.log('all done!');
});

I'm not overly familiar with q so it may be done better.

For completeness, here's a version using bluebird:

var Promise = require('bluebird');

...

var asyncOperationAsPromised = Promise.promisify(asyncOperation);

function performCommand(command) {
  console.log('performing command', command);
  return asyncOperationAsPromised(command).delay(1000);
}

Promise.each(
  [ 'cmd1', 'cmd2', 'cmd3' ],
  performCommand.bind(null)
).then(function() {
  console.log('all done!');
});
robertklep
  • 198,204
  • 35
  • 394
  • 381
  • Thanks that was exactly what i was looking for. Within the asyncOperation i additionally use Q.defer() to return a resolved or rejected promis. – solick Nov 13 '15 at 09:56
1

A common design pattern for sequencing a bunch of async operations on an array is to use .reduce() like this:

var cmdArr = ['cmd1', 'cmd2','cmd3'];

cmdArr.reduce(function(p, item) {
    return p.delay(1000).then(function() {
        // code to process item here
        // if this code is asynchronous, it should return a promise here
        return someAyncOperation(item);
    });
}, Q()).then(function(finalResult) {
    // all items done here
});

Note, I've also shown where you can insert Q's .delay() as requested.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • @solick - I'm just curious why you didn't go with the simple design pattern based on `.reduce()` and using Q's `.delay()` like you asked? – jfriend00 Nov 13 '15 at 17:43