0

I have a bluebird promise, which runs a check. If this check is true, it can continue on. However, if this check is false, it needs to spawn an asynchronous process, which it must wait to complete before continuing.

I have something like the following:

var foo = getPromise();

foo.spread( function (error, stdout, stdin) {
    if (error) {
        // ok, foo needs to hold on until this child exits
        var child = spawn(fixerror);
        child
            .on('error', function (e) {
                //I need to error out here
            })
            .on('close', function (e) {
                //I need to have foo continue here
            });
    } else {
        return "bar";
    }
});

How would I go about doing that?

MirroredFate
  • 12,396
  • 14
  • 68
  • 100
  • Why does your `.spread()` handler take a function with an `error` as the first argument? That does not seem very promise-like. Usually, an error would cause the promise to reject, not resolve. – jfriend00 Apr 14 '16 at 00:37
  • @jfriend00: Sounds like `stderrString` to me, given the other two parameter names. An external process was executed and everything went fine, but it did write something to stderr. – Bergi Apr 14 '16 at 00:45
  • possible duplicate of [How do I convert an existing callback API to promises?](http://stackoverflow.com/q/22519784/1048572) - if there is anything not covered there, please [edit] your question with an explanation how your attempt did not work. – Bergi Apr 14 '16 at 00:47

2 Answers2

1

First off why does your .spread() handler take a callback with error as the first argument. That does not seem correct. An error should cause a rejection, not a fulfillment.

But, if that was indeed the way your code works, then you just need to return a promise from within your .spread() handler. That promise will then get chained to the original promise and you can then see when both are done:

getPromise().spread( function (error, stdout, stdin) {
    if (error) {
        // ok, foo needs to hold on until this child exits
        return new Promise(function(resolve, reject) {
            var child = spawn(fixerror);
            child.on('error', function (e) {
                //I need to error out here
                reject(e);
            }).on('close', function (e) {
                // plug-in what you want to resolve with here
                resolve(...);
            });
         });
    } else {
        return "bar";
    }
}).then(function(val) {
    // value here
}, function(err) {
    // error here
});

But, probably, your .spread() handler should not have the error argument there and that should instead cause a rejection of the original promise:

getPromise().spread( function (stdout, stdin) {
    // ok, foo needs to hold on until this child exits
    return new Promise(function(resolve, reject) {
        var child = spawn(fixerror);
        child.on('error', function (e) {
            //I need to error out here
            reject(e);
        }).on('close', function (e) {
            // plug-in what you want to resolve with here
            resolve(...);
        });
    });
}).then(function(val) {
    // value here
}, function(err) {
    // error here
});
jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • Good call on the error piece- instead of using a then, rejected the error and used a catch to manage the resolution piece. – MirroredFate Apr 15 '16 at 00:39
1

wrap the spawn or any other alternative route in promise function, then keep the flow as, (sample code):

promiseChain
  .spread((stderr, stdout, stdin) => stderr ? pSpawn(fixError) : 'bar')
  .then(...

// example for promisified spawn code: 
function pSpawn(fixError){
    return new Promise((resolve, reject) => {        
        spawn(fixError)
          .on('error', reject)
          .on('close', resolve.bind(null, 'bar'))        
    })
}
mido
  • 24,198
  • 15
  • 92
  • 117