BaldEagle
BaldEagle

Reputation: 1018

Why would JavaScript Promises sometimes neither use .catch nor use .then?

This could be a question with a zillion answers or you'll otherwise need to see my actual code to help me. And it could be that there's one cause (or a small number of causes) for the behavior I'm seeing. First question: Which is it? If the former, I'll withdraw the question so people don't waste their time. I cannot share the code and it's longer than is appropriate here anyway.

I'm writing JavaScript in Node.JS using bluebird for Promises. Parts of my code fit this model.

const Promise = require('bluebird');
function a() {
  return new Promise(function(resolve, reject) {
    <... do something>
    <either> return resolve();
    <or> return reject();
  })
}

a()
.catch(error => { console.log('Used .catch   error=', error) })
.then(result => { console.log('Used .then   result=', result) });

In some parts of my code fitting this model, I see the results of one of the log statements. In other parts of my code fitting this model, I see neither. In the latter parts, when I trace execution path with the debugger, after it finishes with a, it puts the green highlight on (error in .catch(error => { and next on } closing a Promise that contains a, its .then, and its .catch, and next (after going through some bluebird code) on } closing a function that contains that same Promise.

JSHint doesn't identify anything related.

I saw very similar behavior when I was using native Promises. I solved it then by substituting bluebird Promises. Now I see bluebird doing the same, though in different places.

If this is something with a known and easily described cause, I'll really appreciate the help. If it's bigger than that, this question probably doesn't belong on Stack Overflow; I'll withdraw it.

Thanks in advance.

Upvotes: 2

Views: 953

Answers (1)

Benjamin Gruenbaum
Benjamin Gruenbaum

Reputation: 276386

Ok, let's start with something completely different. Chances are you should never be using the promise constructor, ever.

The promise constructor is for converting things that are not promise returning into things that are promise returning. If you're using bluebird, you should be using Promise.promisifyAll to do that swiftly and efficiently for you.

Promises are about making your life easier not harder. Writing a ton of boilerplate would beat this purpose. It is likely some frustrating is caused from incorrectly converting a callback API. This is hard to get right - for example, the promise constructor completely ignores return values.

Your code uses catch which recovers from errors. A little like:

try {
    var result = doSomething();
} catch (error) {
   console.log('Used .catch   error=', error);
}
console.log('Used .then   result=', result);

Using .catch means you recover from the errors. It means your code can gracefully handle exceptional conditions. If you need to signal in a catch that your code does not recover from the error - you need to rethrow the exception:

.catch(e => { console.log("Got ", e); throw e; })

Since you're using bluebird and modern Node - might I suggest taking a look at generators? http://bluebirdjs.com/docs/api/promise.coroutine.html

Upvotes: 5

Related Questions