What is the equivalent Bluebird promise err logging to this:
if (err) {
console.log(err);
res.send(err);
}
For this:
}).catch(Promise.OperationalError, function(e){
// handle error in Mongoose save findOne etc, res.send(...)
}).catch(function(e){
// handle other exceptions here, this is most likely
// a 500 error where the top one is a 4XX, but pay close
// attention to how you handle errors here
});
Bluebird will automatically log unhandled rejections for you. If you wish to send a server response on an error and mark the chain as handled you can do:
.catch(function(err){
console.log(err);
res.send(err);
throw err; // this is optional, if you don't want to mark the chain as handled.
});
Related
The sequelize create statement has an error and I would like to handle that error. Since the create statement has the error I need to handle promise rejection. How do I do that in code? Tried to look at the sequelize documents but unable to work it out.
db.Employee.create(empData,
{
include:[
{
model: db.EmployeeDetails
}
]
}).then(function(newEmployee){
res.json(newEmployee);
}).catch(function(err){
return next(err);
});
The error is on the create and so the webpage just gives an internal server error. I was under the impression that the catch was something that handled the promise rejection and failure. In this case, how can I handle the promise rejection in code. An example would be greatly appreciated.
By doing next(err), by default, you send a 500 Internal Server Error message. If you use Express, and want to show a custom error, just append a status code which is not 5xx to the error:
General Usage:
const err = new Error("my custom error")
err.statusCode = 400
next(err)
In your snippet, do:
db.Employee.create(empData, {
include:[
{
model: db.EmployeeDetails
}
]
}).then(function(newEmployee){
res.json(newEmployee);
}).catch(function(err){
err.statusCode = 400
next(err);
});
If you haven't set your error handler in Express you will need to add somewhere at the end of the main file this:
// Error Handler
app.use(function(err, req, res, next) {
console.error(err)
if (!err.statusCode) err.statusCode = 500;
let msg = err.message
// Do not expose 500 error messages in production, to the client
if (process.env.NODE_ENV === "production" && err.statusCode === 500) {
msg = "Internal Server Error"
}
res.status(err.statusCode).send(msg)
})
Your webpage showing a 500 error means the issue was caught / working as intended. What you need to do is figure out how to handle displaying that error in a pretty format - this being a UI task. If you want a 'patch' for hiding the issue, change your return to a res. This will trick your browser with a 200 status and hide the error.
I do want to add, I recommend trying async/await for sequelize. There's a good amount of usage examples with it.
Promise
db.Employee.create(empData,
{
include:[
{
model: db.EmployeeDetails
}
]
}).then(function(newEmployee){
res.json(newEmployee);
}).catch(function(err){
// Temporary patch
res.json("pretty error message");
});
Async/Await version
async function createEmployee(empData) {
try {
return await db.Employee.create(empData, {
include:[ { model: db.EmployeeDetails } ]
});
} catch (err) {
// Handle error here
return err;
}
}
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
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); });
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.
I have set up an uncaughtException event listener in node js:
process.on('uncaughtException', function (err) {
console.log('uncaughtException: ');
console.log(err);
process.exit(1);
});
To test it I tried the following. At one time:
callNonExistantFunction();
And at another:
throw new Error('test error');
In both cases, the exceptions were caught, but the value of the err parameter in the callback function was an empty object: {}. Is there any way to get the details of the error? I'm working on a Windows machine if it matters.
Thanks.
I'm using Express (4.x), Redis (2.8) and Bluebird (2.x) - Needed to string together multiple Redis calls to return a response:
var promise = require('bluebird');
var redis = require('redis');
var redis = redis.createClient(6379,process.env["REDIS_ENDPOINT"],{});
promise.promisifyAll(redis);
// GET
exports.inOffers = function (req, res) {
return redis.smembersAsync('advertisers')
.map(function(advId){
console.log('advId',advId);
return redis.smembersAsync('advertiser:'+advId+':inoffers')
.map(function(inOfferId){
console.log('offerId: ',inOfferId);
return redis.hgetallAsync('advertiser:'+advId+':inoffer:'+inOfferId);
})
})
.done(function(inOffers){
console.log('InOffers: ',inOffers);
res.json({inOffers: inOffers})
})
.catch(function(err){
console.log((new Date).toUTCString()+" [ERROR] ", err);
res.writeHead(500);
res.end();
});
};
According to the logs, the data is gathered correctly from Redis, but I get the following error, instead of a response:
/var/app/current/node_modules/bluebird/js/main/async.js:95
throw res.e;
^ Error: Can't set headers after they are sent.
Any ideas? I'm new to bluebird, probably messed something up...
You should replace .done with .then
To clarify, and as Benjamin pointed out below, your issue is that you are trying to set the headers on the response object after it has already been sent to the client. I'm not sure if there is other middleware that is returning a response, or if it something with the .done/.catch you have there. I would try the code below for the end of your promise chain, although I'm not sure it will help. Another tip - per bluebird docs, you don't need to use 'done', although you can if you want to (bluebird .done docs). If you do use .done, it should be the last thing in your promise chain (although you can have both fulfilled and rejected handlers on it, just like .then).
.done(function(inOffers){
console.log('InOffers: ',inOffers);
res.json({inOffers: inOffers})
}, function(err){
console.log((new Date).toUTCString()+" [ERROR] ", err);
res.writeHead(500);
res.end();
});
In my application i want to create own module to capture my application error using uncaughtException.If i create uncaughtException in same module means its capturing errors but if i create that uncaughtException in separate module.Then call that module means its not capturing erros.Can anyone help me to fix this issue.
module1.js
var errorModule=require('./module2');
var err = new Error('Something went terribly wrong');
errorModule.captureError(err);
module2.js
module.exports.captureError=function(err){
process.on('uncaughtException', function(err) {
console.log(err);
});
}
Try this:
// module1.js
var errorModule=require('./module2');
errorModule.captureErrors();
throw Error('Something went terribly wrong');
// module2.js
module.exports.captureErrors = function() {
process.on('uncaughtException', function(err) {
console.log('an error occurred', err);
});
};
A few things to notice:
process.on('uncaughtException', ...) installs an event handler to catch uncaught exceptions; your code tries to pass an error to it, but that seems to defeat what you're writing ('to capture my application error using uncaughtException');
Uncaught exceptions are errors which are thrown (throw Error(...));
If you want the code in your module1 to work, module2 needs to look like this:
module.exports.captureError = function(err) {
console.log(err);
};
But that has nothing to do with uncaughtException.