2

When I run the following in Chrome, I get an "Uncaught (in promise) failure" error message:

var p = new Promise(function(resolve){
 throw "failure";
})

p.then(function(){
 console.log("success");
})

p.catch(function(err){
 console.log(err);
});

I don't get an error if I run:

var p = new Promise(function(resolve){
 throw "failure";
})

p.then(function(){
 console.log("success");
}).catch(function(err){
 console.log(err);
});

or this:

var p = new Promise(function(resolve){
 throw "failure";
}).catch(function(err){
 console.log(err);
});

What's going on here? I'm relatively new to Promises, so I'm probably missing something simple...

Al R.
  • 2,430
  • 4
  • 28
  • 40
  • 3
    It's the promise created by `p.then(…)` that is rejected without a handler – Bergi Mar 12 '18 at 21:29
  • I'm sure there's a duplicate, but [this](https://stackoverflow.com/q/38451166/1048572) is the only thing I could find – Bergi Mar 12 '18 at 21:59

2 Answers2

0

The first case didn't work for you because you tried to catch the error from the Promise directly where you was using in the same time .then, in this case you catch the error from the .then. In the other hand, where there is no .then you can catch directly from the Promise object.
.catch is a shorter alias for .then. The catch() method returns a Promise object and only deals with cases where the initial promise is rejected. It has the same effect as a call to Promise.prototype.then(undefined, ifRejected) (this is actually what happens in the engine, obj.catch(onRejected) is translated into obj.then(undefined, onRejected)) . So you can not put Promise.catch().

Nadhir Houari
  • 390
  • 4
  • 10
0

Lesson here. If you chain your .then() and .catch() handlers directly to the promise (without creating an intermediate p variable and intermediate promise chains) and you have a .catch() handler at the end of every chain, you are very unlikely (perhaps completely unlikely) to get the "unhandled promise rejection" message.

Based on other occurrences of this I've seen both in my own code and here on stack overflow, it seems to me that the interpreter or promise library is somewhat guessing when the unhandled rejection situation occurs and is not perfect at its guessing.

In your case, the interpreter saw that p.then() does not have a .catch() handler and then saw p get rejected. So, that promise chain does not actually have a .catch() handler. So, that promise chain will end with a rejection and there was no handler. That triggers the warning.

It wasn't smart enough to see that there was a separate p.catch() or didn't think that justified not showing the warning.

As you've already discovered, this will always be safe:

new Promise(function(resolve){
    throw "failure";
}).then(function(data) {
    console.log(data);
}).catch(function(err){
    console.log(err);
});

because there are no promise chains that can ever get a rejection that isn't caught by a .catch(). Think twice about saving a promise to a variable at all - just make a single promise chain (or branched chains inside of .then() handlers if needed). I've almost never found it required to save a promise into a variable except occasionally when I'm returning it from a function and executing some code in the function after the promise was created. Usually, you can just do:

f().then(...).then(...).catch(...);
jfriend00
  • 683,504
  • 96
  • 985
  • 979