node.jspromisewarningsunhandled

Have .catch in chain but getting UnhandledPromiseRejectionWarning using Node 6


I have this promise chain.

com.openPort(port).then(port => {
                        _.pTimeout(3000, com.sendPort(port, NCD.gen(args.cmd)))
                            .then(received => {
                                console.log('complete response: ', NCD.parse(received));
                                Debug.L1('resolved num data listeners: ', port.listenerCount("data"));
                            })
                    })
                    .catch(function(e) {
                        console.log('error: ', e)
                    });

and I'm testing the timeout promise by sending a bogus command that will make the sendPort promise be unresolved. The timeout promise wins the race throwing a reject but a warning comes before the .catch handles the rejection.

here's the timeout promise race

pTimeout: function(timeout, promise) {
        return Promise.race([
            promise,
            new Promise(function(resolve, reject) {
                setTimeout(function() {
                    reject('\nTimed out');
                }, timeout);
            })
        ]);
    }

console shows

  (node:9616) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): 
  Timed out

you can see after the warning the .catch putting "Timed out" to the console so it was handled...albeit improperly??

I'm using node 6, which it seems by other posts, now warns if it's not handled in the first tick. I can't grok how to fix this from those. How should this be handled? I tried putting a .catch right after the timeout promise but still get the warning before the .catch.


Solution

  • The promise returned by _.pTimeout() is orphaned and rejections are not handled. To handle them, you either need a .catch() on that specific promise or you need to add a return so that it is chained to the parent promise so it will get caught by the higher level .catch(). I'd suggest returning/chaining it since you rarely wanted a promise to just proceed at its own pace and not be connected at all to the parent promise:

    com.openPort(port).then(port => {
        return _.pTimeout(3000, com.sendPort(port, NCD.gen(args.cmd))).then(received => {
            console.log('complete response: ', NCD.parse(received));
            Debug.L1('resolved num data listeners: ', port.listenerCount("data"));
        });
    }).catch(function (e) {
        console.log('error: ', e)
    });