Is it possible to implement the below way to handle the exception in expressjs Framework:
actually, I am calling a method ( Fun1 ) by a passing parameter (key_id, user_id). Like below:
data = Fun1(key_id=123, user_id=234)
so, if above line returns an error then I need to call other function (Fun2) otherwise no need to call this (Fun2)
I am implementing like this way, but it's not working( Means, when try block return error then catch block, is not executing)
try{
var data = Fun1(key_id=123, user_id=234);
}
catch(err){
var data = Fun2(key_id=123, user_id=234);
}
is there any other way to handle?
If the Fun1 throws an error then the above mentioned implantation works perfect and moves to the catch block and executes the Fun2 but if it returns a value then this does not work
Syntax for throwing an error
throw new Error("<Error Message>")
Related
I try to promisify SFTPWrapper and hit this problem. I am not sure if it happens to other object or not.
So if I just promisify one SFTPWrapper function, say readdir, bluebird will have unhandledRejection : "Cannot read property 'readdir' of undefined" error. I tried util.promisify, the same error too.
But if promisifyAll(SFTPWrapper) and it work as expected. But why is that ?
---- update -----
The code I use,
var Client = require('ssh2').Client
var conn = new Client()
conn.on('ready', function() {
conn.sftp(async function(err, sftp) {
if (err) throw err
try {
// promisify will have Cannot read property 'readdir' of undefined error
// both bluebird and util have the error
//let readdirAsync = Promise.promisify(sftp.readdir)
let readdirAsync = util.promisify(sftp.readdir)
list = await readdirAsync(remotePathToList)
// Promise.promisifyAll(sftp) work
const sftp2 = Promise.promisifyAll(sftp)
let list = await sftp2.readdirAsync(toRead)
You don't show exactly where that error "Cannot read property 'readdir' of undefined error" occurs. If it occurs on this line of code:
let readdirAsync = util.promisify(sftp.readdir);
Then, the problem is that sftp is undefined. But, it doesn't appear that that is exactly the issue because you say that const sftp2 = Promise.promisifyAll(sftp) does work.
So, I'm guessing that the problem occurs when you try to use readdirAsync. If that's the case, then it's probably because you lost the sftp parent when you did let readdirAsync = util.promisify(sftp.readdir) and that is somehow important to the readdir method implementation. If that is indeed the case, then you can do this:
let readdirAsync = util.promisify(sftp.readdir).bind(sftp);
To make sure the parent object stays bound to the method. Because Bluebird's .promisifyAll() puts the new methods on the original object and you call them as methods on the object, not as plain functions, this binding to the original object happens automatically when you call them as sftp2.readdirAsync(). You could do that also as in:
sftp.readdirAsync = util.promisify(sftp.readdir);
And, then you could call sftp.readdirAsync(...).then(...).catch(...) and they'd be bound appropriately to the sftp object.
P.S. Using if (err) throw err inside an async callback is NEVER good error handling. You literally should never write that line of code inside an async callback unless the caller of that async callback has an explicit handler for that exception (which is usually not the case). All it does is throw an exception into async oblivion with no opportunity for actual error handling anywhere else in your code.
First of all, I know one way to catch uncaught errors is use process.on('uncaughtException', err, function() {});.
I want to know how I can pass more details, or more context to the error. I want to be able to get the variables used. I'm not trying to recover from the error, only get more details of my environment when the error happened before shutting down the process. Yeah, the stack trace is nice, but I'd like to know how to replicate the error.
For example, I have this function:
function doTheBatman(var1) {
var var2 = 'whatever';
// this causes an uncaught exception later in the code
}
On process.on, I want to be able to access var1 and var2.
process.on('uncaughtException', function(err) {
// process.whatever doesn't contain any active variables
});
A synchronous exception in an Express route handler will be caught by Express itself and the exception will be passed off the default Express error handler where you can catch it yourself and the exception context is passed to that default express error handler.
You can see this code inside of Express where a route handler gets called:
Layer.prototype.handle_request = function handle(req, res, next) {
var fn = this.handle;
if (fn.length > 3) {
// not a standard request handler
return next();
}
try {
fn(req, res, next);
} catch (err) {
next(err);
}
};
The call to next(err) will pass the exception object off to the default Express error handler (which you can install a handler for).
If your code is throwing an exception inside of an asynchronous callback, then that is more complicated to catch in action. If you're using regular async callbacks (not promises), then the only way I know of to catch those at a meaningful spot is to put a try/catch inside of every async callback so you can capture the local stack info.
If you use promises at the lowest level and only program your logic and asynchronous code flow use promise functionality, then an exception in a promise handler will automatically turn into a rejected promise and certain promise libraries (like the Bluebird library can be configured to give you a pretty full stack trace of where things went wrong). Promises have this advantage because every promise .then() or .catch() handler is automatically wrapped in a try/catch handler and those are turned into promise rejections which propagate up the chain to the first .catch() handler they find.
For the non-Express example you just added to your question, you will just have to put a try/catch somehwere in the local neighborhood to catch a local synchronous exception:
function doTheBatman(var1) {
try {
var var2 = 'whatever';
// this causes an uncaught exception later in the code
} catch(e) {
console.log(e);
}
}
You can even set a debugger breakpoint in the catch handler and then examine variables in that scope when it is hit. I don't know of any way to examine the local variables at the point of the exception from the uncaughtException handler. err.stack should give you the stack trace, but not variable values.
Express/frameworks may offer more elegant/robust solutions, but if you're truly after what your question asks for... why not just capture variables outside of the functions scope? This is typically nasty and not considered best practice, but if you have a function that you know could be susceptive to failing often, perhaps the quick and dirty solution is what you need. You could always refine this later, but hopefully this demonstrates the approach...
var transactionVars = {};
function clearTransaction() {
transactionVars = {};
}
function doTheBatman(var1) {
transactionVars['var2'] = 'whatever';
// [...] bunch of stuff, possibly blowing up...
clearTransaction(); // we made it this far? cool, reset...
}
process.on('uncaughtException', function(err) {
console.log(transactionVars['var2']); // whatever
});
Furthermore, if you want to really dirty (in case these two functions are in two files) you can always tack transactionVars on the global object.
This is essentially a poor mans event emitter pattern, which I would highly recommend refactoring into once you grasp the general flow of how this works...
I am trying to test the following code:
var archive = function(callback){
call to this.archive() here...
}
var map = function(callback){
call to this.map() here...
}
async.parallel([map, archive], function(error){
handle errors here...
})
I am testing that the handle errors functionality is working by stubbing the archive and map functions so that one of them returns an error:
var mapStub = sinon.stub(MyClass.prototype, 'map').yields("mock error",null );
var archiveStub = sinon.stub(MyClass.prototype, 'archive').yields(null,null );
The problem I am having is that the archiveStub does not seem to be being used, as I am getting errors from a function which is called by that function (which would be expected if that function was called as I have not initialised variables for this test).
I have another test, where the archive function returns an error instead of the map function, and this test passes without seeming to call either of the stubbed methods instead of the stubs.
var mapStub = sinon.stub(MyClass.prototype, 'map').yields(null,null );
var archiveStub = sinon.stub(MyClass.prototype, 'archive').yields("mock error",null );
You want to use yieldsAsync instead of yields, otherwise the error is yielded prematurely (before all the parallel "tasks" have been started) and async.map() stops any further processing (using yields basically turns it into a synchronous operation).
I am using Azure Mobile services-NodeJS backend, and when programming it, I always face this doubt - let me explain using the below code snippet
//--------------------------------------------------------------------------
function addUserToDB(request, response){
///some code here
var theUser = request.user;
///get the user's entity object
try {
objAppUser = buildAppUserEntityObj(theUser, request); //for simplicity sake, lets say this is not asynchronous function
}
catch (err) {
console.log ('error in addUserToDB when calling buildAppUserEntityObj'); //****????****
request.respond(statusCodes.BAD_REQUEST, err);
return; // ##????## is a 'return' needed here to avoid the execution of the code below, or should I assume that the function will return once request is responded (request.respond) in above line.
}
....code to add userEntity to DB
//some more code in case of successful try above, can I assume there is no way this code will be reached in case of error in the above try-catch
// ofcourse I can move this code in the 'try' block above, but I am just trying to understand what happens if above try ends in catch block for some reason and there is no 'return' at the end that catch block.
}
//--------------------------------------------------------------------------
function buildAppUserEntityObj(user, request) {
if ( user.level === 'anonymous' ) { //ideally this would be called in above function, but I am putting this here just to throw an example.
console.error('Anonymous User' );
request.respond(statusCodes.BAD_REQUEST, message); //will this request.respond will send the response to client immediately, or will it be passed on as error the try-catch of above 'addUserToDB' function
return; // ##????## also, is 'return' needed here to avoid the execution of the code below,
}
....code to build a User entity object based on some business logic
}
//--------------------------------------------------------------------------
I guess, it all boils down to three questions:
1. Is 'return' needed in the two places (marked by ##????## in the above two functions?
2. Will the message (marked by //****????**** ) be logged in case user.level === 'anonymous'
3. request.respond vs response.send , whats the difference?
I believe these doubts are because of my lack of thorough expressJS knowledge, so while I am going thru azure/express.js documentation again, I thought I would throw my doubt here to the expert community to get a more clear explanation.
Many thanks.
First
In the second return (insode of buildAppUserEntityObj function, I believe you want it to be:
throw new Error("Anonymous user is not allowed")
Otherwise, even if user is anonymous, your catch code will never execute anyway.
You need the first return;, otherwise it will continue executing the code below.
Second
Message will be logged, if you fix the code described in First paragraph.
Third
There is no request.respond in standard Node.js http module. Can you clarify, what module are you using? That module's API shall answer your question anyway.
I am writing a node js application. I am using request and cheerio to load a set of URLs and get a bunch of information for the site, now let's assume all I am trying to get is the title:
var urls = {"url_1", "url_2", "url_3",...,"url_n"};
for(var i=0; i<urls.length; i++)
{
getDOMTitle(urls[i],function(error,title){
if(error)
console.log("Error while getting title for " + urls[i]);
else
console.log("The title for " + urls[i] + " is " + title);
});
}
This is how my getDOMTitle method looks:
function getDOMTitle(urlReq,callback)
{
var request = require('request');
var cheerio = require('cheerio');
request({url:urlReq},function(error, response, doc){
var $ = cheerio.load(doc);
if(error)
{
callback(true,null);
}
else
{
$('title', 'head').each(function (i, elem) {
var title = $(this).text();
callback(false,title);
});
}
}
}
In the case where the module throws an uncaught exception, how do I handle that situation?
I have tried adding the following:
process.on('uncaughtException', function (err) {
console.error(err);
console.log("Node NOT Exiting...");
callback(true,null);
});
When I do that, I get an error saying I cannot set the headers once they have been sent. If I remove the callback from the process error handling, I do not see that error but the client spins for a long time because I assume we are never calling the callback.
How can I solve this?
Also, I have read somewhere that you can catch uncaught exceptions at the application level so you don't have to replicate the code to catch it in every method, is that possible? and if it is and the method that threw the exception is expected to callback with some information, how can that be achieved?
Thank you,
To answer your stated question, using an uncaught exception handler as a general error-trapping mechanism is commonly regarded as poor design. It's a false economy to use it to handle anything other than non-recoverable situations where you just need to do some cleanup before exiting.
You've got some problems in your example code. In your for loop, all the callbacks are going to report that they were working with the very last URL in your array because they're all referring to the same copy of i, which will be at its highest value by the time any of them execute. You need to use a helper function or an immediate function invocation to give each callback a private copy of i.
In getDOMTitle the error callback should be callback(error) and the code in your loop should include the returned value in the error message. The success callback should use null as its first parameter, though this is just a matter of convention.