Reputation: 2821
using nodejs v. 7.5.0 I'm getting UnhandledPromiseRejectionWarning && DeprecationWarning I know its part of new features since node 6.6 but the thing I don't understand is that I'm catching that promises just after caching it into a variable. If I don't cache it no warning is thrown. this is the code that throws the error:
let verifyPromise = verifyToken(id_token);
verifyPromise.catch((err) => {
log(err);
});
let verifyOkPromise = verifyPromise.then((login) => {
return DB_API.getTokenById(id_token);;
});
verifyOkPromise.catch((err) => {
log('error in finding token: ', err);
});
verifyOkPromise.then((dbRes) => {
log('loggin res in finding token: ', dbRes);
});
where verifyToken() is a function that checks google auth token and returns a promise. node output is the following:
error in finding token: { CouchbaseError message: 'The key does not exist on the server', code: 13 }
(node:10961) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): CouchbaseError: The key does not exist on the server
(node:10961) DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
as you can see the promise error branch is regularly catched as it logs as expected but I still get the warning!!!!
while if I just append the catch like this:
verifyPromise.then((login) => {
return DB_API.getTokenById(id_token);;
}).catch((err) => {
log('error in finding token: ', err);
});
NO Warning is given!!! I think I'm missing something subtle but I don't understand what could be. Some one have any clues? thanks in advance
Upvotes: 3
Views: 1952
Reputation: 276496
You're using Node 7.5, you should consider async/await
. Chad's answer is well written and correct, but here's how I'd write the code in question:
async function whateverYoureDoing(id_token) {
const token = await verifyToken(id_token);
// catch will automatically propagate.
//You can use regular try/catch and if rethrow your own custom TokenInvalidError object
const dbRes = await DB_API.getTokenById(id_token);
console.log('loggin res in finding token: ', dbRes);
}
Note: You no longer need to add .catch
and log error with promises - that's the point of the unhandledRejection
tracking feature :) Logging should be generally done at a top level since promises work great with exceptions anyway.
Upvotes: 1
Reputation: 4623
This issue is happening because it is not the original promise that ultimately fails, it is the then()
! You are not storing the result of
verifyOkPromise.then((dbRes) => {
log('loggin res in finding token: ', dbRes);
});
It is the call to then()
here that ultimately triggers the resolution of the Promise chain. You're trying to handle the catch from the original call, but it's the chain that fails. Here are three simplified versions of what you're trying to do. The first matches your workflow. The second matches how these are normally written (but a pattern you didn't want to use). The third rewrites your pattern to work properly but using results assigned to variables.
let Promise = require('bluebird');
function forceReject() {
return Promise.reject('deliberately failed');
}
let p = forceReject('12345');
// This will produce an Unhandled Rejection error
/*
p.then(res => { console.log('succeeded: ', res); });
p.catch(err => { console.log('failed: ', err); });
*/
// This will work but it's not the pattern you prefer
/*
p.then(res => {
console.log('succeeded: ', res);
}).catch(err => {
console.log('failed: ', err);
});
*/
// This will also work! Note the assignment of the result of p.then()...
let q = p.then(res => { console.log('succeeded: ', res); });
q.catch(err => { console.log('failed: ', err); });
Upvotes: 4