2

I am using the node.js libraries nomnom for command line parsing and bluebird's promises.

Nomnom offers to execute commands via a callback. Unfortunately, the callback doesn't support returning promises.

I was wondering, what is the best way to handle this interface mismatch? I was thinking adding a busy loop that blocks until a promise is resolved / rejected (using isPending ) in this case. Is there a better way ?

var parser = require("nomnom");
parser.command('somecommand').callback(function(opts) {
  var p = thisFuncReturnsAPromise();
  //have to block here since
  //nomnom expects at the end of the callback that processing of the command is done.
})
JE42
  • 4,881
  • 6
  • 41
  • 51
  • just write an anon then method and call the callback with the argument from inside. don't block. – dandavis Nov 19 '14 at 20:24
  • You'd promisify it. It's a good question - let me find the duplicate real quick. – Benjamin Gruenbaum Nov 19 '14 at 20:30
  • Not sure how to promisify it. Added sample code to make the case a bit more clear. – JE42 Nov 19 '14 at 20:49
  • I don't think this is a duplicate in this case, since nomnom needs the callback. – JE42 Nov 19 '14 at 20:53
  • @JE42: If you say that the `callback()` method expects a synchronous callback, but you want to do something asynchronous and wait for it, then this is impossible. It doesn't have to do with promises (`thisFuncReturnsAPromise()` could as well be `thisFuncTakesACallback()`), but you just cannot use `nomnom`. File a bug that you need async support, or fork the lib on your own. – Bergi Nov 19 '14 at 21:11
  • Ok. so there is no node.js api that forces the processing of async code in the middle of synchronous code ? – JE42 Nov 19 '14 at 21:15
  • @BenjaminGruenbaum i think it would be great if you could remove the duplicate flag, as this is clearly not the same. – JE42 Nov 19 '14 at 21:23
  • I think it still is - it's the same core problem (working with promises in a callback API) but as you wish. I have reopened the question. – Benjamin Gruenbaum Nov 19 '14 at 21:49
  • 1
    I think that @Bergi has had the key insight here. In order to better understand the word "impossible", I took a deeper dive into bluebirds code and Node.js async processing APIs. It does not allow any function scheduled via process.nextTick to be executed during another function. Since bluebird executes the resolve via process.nextTick, there is no way to wait for this to happen without changing the 3rd party library. the only way would be if node.js had offered an API like "process.executeEveryThingThatWasScheduledForNextTickNow()". – JE42 Nov 19 '14 at 21:58

1 Answers1

0
var promise = new Bluebird(function(resolve, reject) { //Create a promise
    myLib.doStuff(function() {
        resolve(); //In a callback you resolve the promise
    });
}); 

promise.then(function() { //Use the promise
    console.log('Stuff done');
});
Arseny Smoogly
  • 600
  • 2
  • 7
  • That's not really how you'd do it in BB. – Benjamin Gruenbaum Nov 19 '14 at 20:31
  • Changed it for the BB behaviour, is it right this way? But the point is, resolve the promise inside the callback. – Arseny Smoogly Nov 19 '14 at 20:45
  • No, bluebird would jsut do `Promise.promisifyAll` on a whole module and convert it to a complaint API in a single command assuming it uses correct node conventions for callbacks. See the question I closed as a dupe. – Benjamin Gruenbaum Nov 19 '14 at 20:49
  • @BenjaminGruenbaum please check out the sample code. I don't think this is a dupe. – JE42 Nov 19 '14 at 20:53
  • @JE42 please check the "2. Plain callback:" option in the dupe - it describes the exact same scenario. – Benjamin Gruenbaum Nov 19 '14 at 20:56
  • 1
    @BenjaminGruenbaum Case 2 describes the case where I have control of the code that requires the result of the callback. Here the roles are flipped. I provide the callback and nomnom can execute code after the callback completes. – JE42 Nov 19 '14 at 21:02