So recently for some unknown reason, I started seeing regular errors in the console. Like this:
(node:147) UnhandledPromiseRejectionWarning: Error: timeout of 1000ms exceeded
at createError (/home/runner/ricebot/node_modules/axios/lib/core/createError.js:16:15)
at RedirectableRequest.handleRequestTimeout (/home/runner/ricebot/node_modules/axios/lib/adapters/http.js:280:16)
at RedirectableRequest.emit (events.js:314:20)
at RedirectableRequest.EventEmitter.emit (domain.js:483:12)
at Timeout._onTimeout (/home/runner/ricebot/node_modules/follow-redirects/index.js:166:12)
at listOnTimeout (internal/timers.js:554:17)
at processTimers (internal/timers.js:497:7)
It also sometimes make my bot's latency go to 30000 ms.
I only have Axios parts in my fun commands and here is one of them (however it still works properly, just logs the error):
const url = 'https://no-api-key.com/api/v2/animals/cat';
let image;
let fact;
try {
const { data } = await axios.get(url);
console.log(data);
image = data.image;
fact = data.fact;
} catch (e) {
console.log(e)
return message.channel.send('An error occured, please try again!');
}
This didn't use to be a thing.
Since your axios call doesn't have a catch it is normal to get this error or warning.
It is important to manage axios requests to prevent these kind of issues. Also, I assume, the sample you show is missing some data because you won't need to define result variables outside of the catch state, so I assume you have a loop or something that can cause this as well.
If you are making calls to same endpoint in a loop or with Promise.all, sometimes you need to limit concurrent requests. If it is not the case please ignore this part.
First of all, make sure to set your axios.default.timeout value correctly to define when to cancel the request if there was is response.
Define a response status check your with your requirements.
function checkStatus(response) {
if (response.status >= 200 && response.status < 300) {
return response;
}
const error: any = new Error(response.statusText);
error.response = response;
throw error;
}
Define a parse code to make sure you always have same structure.
function parseJSON(response) {
return response.data;
}
Define a catch functionality to check errors and decide whether to throw errors or just log them.
function catchError(e){
console.error(e);
// TODO send a message
return null;
}
Let's use them in a single call with .catch.
const myResult = await axios.get(url)
.then(checkStatus)
.then(parseJSON)
.catch(catchError);
console.log(myResult);
if I'm not mistaken, you can't access properties from a promise directly, as declaring a variable from a property is synchronous while your url() method is asynchronous.
The data type of axios.get(url) is Promise when the response is not returned so it doesn't have a data property which you are accessing early on. Therefore you have to wait for the response. As when the response is returned the data type of that method changes to what it is intended to be. That's when you can access the data property
So I think your code should be like the following:
const url = 'https://no-api-key.com/api/v2/animals/cat';
let image;
let fact;
try {
const axiosUrl = await axios.get(url);
const data = axiosUrl.data;
console.log(data);
image = data.image;
fact = data.fact;
} catch (e) {
console.log(e)
return message.channel.send('An error occured, please try again!');
}
Assuming that this block of code is in an async context, it should work fine.I hope this answer was of use for you.
I asked a question on stack overflow earlier, and a kind user suggested some improvements for my code which seemed great, so I started going over my code in order to implement these changes. The problem is that I'm not sure if my reworked code is handling possible errors the same way as the first.
Here's my current code right now:
module.exports.deleteBrand = async (req, res, next) => {
let brandId = req.body.brandId
let brand
try {
brand = await Brand.destroy({
where: {
id: brandId
}
})
} catch (e) {
console.log(e)
}
if (brand) {
res.status(200).json({
brand: brand
})
} else {
res.status(500)
}
}
And this is how I intend to rework it:
module.exports.deleteBrand = async (req, res, next) => {
let brandId = req.body.brandId
try {
let brand = await Brand.destroy({
where: {
id: brandId
}
})
res.status(200).json({
brand: brand
})
} catch (e) {
console.log(e)
res.status(500)
}
}
As you can see, in my first code snippet, the try-catch block surrounds only my database query and then I check if the database query was successful outside the try-catch, and only send the 200 status response if it is. Otherwise, I send a 500 status.
Is my if-else useless in that scenario, considering that if the database query fails, the error would be caught by the catch block? Should the code that returns 500 status be placed in the catch block?
There is a small difference in error handling, yes, but if anything it seems likely to be an improvement. The difference is:
In your first example, an error raised by res.status(200).json({brand: brand}) after successfully retrieving brand from the database is not caught and terminates deleteBrand.
In your second example, that error is caught and results in calling the res.status(500) in the catch block.
json({brand: brand}) might throw an error if brand has any circular references and so can't be converted to JSON. In that case, your res.status(500) will overwrite your previous res.status(200) (assuming response headers haven't been sent yet, which is probably a correct assumption).
Side note: You're using ES2015+ code, which means you can use shorthand property notation and change .json({brand: brand}) to simply .json({brand}).
I'm a beginner in Node/Express.js and I'm trying out some try catch logic but doesn't seem to work as expected.
app.get("/tasks/:id", async (req, res) => {
try {
const _id = req.params.id;
const task = await Task.findById(_id);
if (!task) {
return res.status(404).send("task not found");
}
res.send(task);
} catch (error) {
res.status(500).send("Internal server error");
}
});
from this code sample, I'm making a query to Mongo DB to fetch some task but the problem is that if the task is not found, instead of running through the if statement, the program jumps directly to the catch block hence the if condition is not checked thus resulting to a different error. How can I fix this issue?
This is simply how MongooseJS works - check their Promises documentation and you will see that if a document is not found, an error will be thrown. If you were not using await, the findById() documentation shows how an error is returned if it cannot be found:
// find adventure by id and execute
Adventure.findById(id, function (err, adventure) {});
You can simply modify your route to look like the following:
app.get("/tasks/:id", async (req, res) => {
let task;
try {
task = await Task.findById(req.params.id);
} catch (error) {
return res.status(404).send("task not found");
}
/* perform other checks or actions here if desired */
res.send(task);
});
This is a little more flexible if you want to perform other error-checking; task is declared first so it can be accessible outside the try/catch block, and a 404 error is thrown if the task does not exist.
You can also look at the exists method which will return true or false based on if the document exists, but since you need the actual result that does not make as much sense.
You don't indicate what Task is, but it appears that it is rejecting when it doesn't find anything, rather than returning a false value (which is what you seem to be expecting).
Given that, you should probably just handle the error that it is throwing with something like
} catch ( error ) {
// Will need to adapt this if to something that identifies the error thrown by `getById`
if ( error.message.includes( 'not found' ) ) {
res.status( 404 ).send( 'task not found' );
} else {
res.status( 500 ).send( 'Internal server error' );
}
}
Im new to javascript programming and i am required to make a web app. Node.js will be used as the js runtime environment. In order to minimize the amount of time needed for debugging as the app develops I would like to implement a robust error handling scheme. However, due to my limited background I am not sure if what I am implementing is best practise or if it is even adequate. So any feedback will be accepted.
The function is asynchronous and will use catch to detect if any errors occurred while operating. A try-catch statement will be used to catch any errors. This was done in order to allow for individual error identification from the functions. My aim is to propagate the errors up to the calling function that will handle it in the highest level catch statement (in my case where it is logged *this will change eventually). Any feedback?
create: async function(req, res) {
let data = JSON.parse(req.body.data);
let result;
let request_body;
let sub_networks_lora;
try {
request_body = sub_network_api_request_data(data, 1);
result = await lora_app_server.create_applications(request_body)
.catch(err => {
//Error updating application on lora app server
throw err;
});
await db_sub_networks.create_sub_network(result.data.id, data.sub_network_name, data.network_id)
.catch(err => {
throw err;
//Error creating sub network in database
});
sub_networks_lora = await get_sub_networks()
.catch(err => {
throw err;
//Error getting networks from lora app server
})
sub_networks_lora = JSON.stringify(sub_networks_lora);
res.status(200).send({
sub_networks_lora
});
} catch (err) {
console.log(err)
} finally {}
}
I'm new to node.js although I'm pretty familiar with JavaScript in general. My question is regarding "best practices" on how to handle errors in node.js.
Normally when programming web servers, FastCGI servers or web pages in various languages I'm using Exceptions with blocking handlers in a multi-threading environment. When a request comes in I usually do something like this:
function handleRequest(request, response) {
try {
if (request.url=="whatever")
handleWhateverRequest(request, response);
else
throw new Error("404 not found");
} catch (e) {
response.writeHead(500, {'Content-Type': 'text/plain'});
response.end("Server error: "+e.message);
}
}
function handleWhateverRequest(request, response) {
if (something)
throw new Error("something bad happened");
Response.end("OK");
}
This way I can always handle internal errors and send a valid response to the user.
I understand that with node.js one is supposed to do non-blocking calls which obviously leads to various number of callbacks, like in this example:
var sys = require('sys'),
fs = require('fs');
require("http").createServer(handleRequest).listen(8124);
function handleRequest(request, response) {
fs.open("/proc/cpuinfo", "r",
function(error, fd) {
if (error)
throw new Error("fs.open error: "+error.message);
console.log("File open.");
var buffer = new require('buffer').Buffer(10);
fs.read(fd, buffer, 0, 10, null,
function(error, bytesRead, buffer) {
buffer.dontTryThisAtHome(); // causes exception
response.end(buffer);
}); //fs.read
}); //fs.open
}
This example will kill the server completely because exceptions aren't being catched.
My problem is here that I can't use a single try/catch anymore and thus can't generally catch any error that may be raised during the handling of the request.
Of course I could add a try/catch in each callback but I don't like that approach because then it's up to the programmer that he doesn't forget a try/catch. For a complex server with lots of different and complex handlers this isn't acceptable.
I could use a global exception handler (preventing the complete server crash) but then I can't send a response to the user since I don't know which request lead to the exception. This also means that the request remains unhandled/open and the browser is waiting forever for a response.
Does someone have a good, rock solid solution?
Node 0.8 introduces a new concept called "Domains". They are very roughly analogousness to AppDomains in .net and provide a way of encapsulating a group of IO operations. They basically allow you to wrap your request processing calls in a context specific group. If this group throws any uncaught exceptions then they can be handled and dealt with in a manner which gives you access to all the scope and context specific information you require in order to successfully recover from the error (if possible).
This feature is new and has only just been introduced, so use with caution, but from what I can tell it has been specifically introduced to deal with the problem which the OP is trying to tackle.
Documentation can be found at: http://nodejs.org/api/domain.html
Checkout the uncaughtException handler in node.js. It captures the thrown errors that bubble up to the event loop.
http://nodejs.org/docs/v0.4.7/api/process.html#event_uncaughtException_
But not throwing errors is always a better solution. You could just do a return res.end('Unabled to load file xxx');
This is one of the problems with Node right now. It's practically impossible to track down which request caused an error to be thrown inside a callback.
You're going to have to handle your errors within the callbacks themselves (where you still have a reference to the request and response objects), if possible. The uncaughtException handler will stop the node process from exiting, but the request that caused the exception in the first place will just hang there from the user point of view.
Very good question. I'm dealing with the same problem now. Probably the best way, would be to use uncaughtException. The reference to respone and request objects is not the problem, because you can wrap them into your exception object, that is passed to uncaughtException event. Something like this:
var HttpException = function (request, response, message, code) {
this.request = request;
this.response = response;
this.message = message;
this.code = code || 500;
}
Throw it:
throw new HttpException(request, response, 'File not found', 404);
And handle the response:
process.on('uncaughtException', function (exception) {
exception.response.writeHead(exception.code, {'Content-Type': 'text/html'});
exception.response.end('Error ' + exception.code + ' - ' + exception.message);
});
I haven't test this solution yet, but I don't see the reason why this couldn't work.
I give an answer to my own question... :)
As it seems there is no way around to manually catch errors. I now use a helper function that itself returns a function containing a try/catch block. Additionally, my own web server class checks if either the request handling function calls response.end() or the try/catch helper function waitfor() (raising an exception otherwise). This avoids to a great extent that request are mistakenly left unprotected by the developer. It isn't a 100% error-prone solution but works well enough for me.
handler.waitfor = function(callback) {
var me=this;
// avoid exception because response.end() won't be called immediately:
this.waiting=true;
return function() {
me.waiting=false;
try {
callback.apply(this, arguments);
if (!me.waiting && !me.finished)
throw new Error("Response handler returned and did neither send a "+
"response nor did it call waitfor()");
} catch (e) {
me.handleException(e);
}
}
}
This way I just have to add a inline waitfor() call to be on the safe side.
function handleRequest(request, response, handler) {
fs.read(fd, buffer, 0, 10, null, handler.waitfor(
function(error, bytesRead, buffer) {
buffer.unknownFunction(); // causes exception
response.end(buffer);
}
)); //fs.read
}
The actual checking mechanism is a little more complex, but it should be clear how it works. If someone is interested I can post the full code here.
One idea: You could just use a helper method to create your call backs and make it your standard practice to use it. This does put the burden on the developer still, but at least you can have a "standard" way of handling your callbacks such that the chance of forgetting one is low:
var callWithHttpCatch = function(response, fn) {
try {
fn && fn();
}
catch {
response.writeHead(500, {'Content-Type': 'text/plain'}); //No
}
}
<snipped>
var buffer = new require('buffer').Buffer(10);
fs.read(fd, buffer, 0, 10, null,
function(error, bytesRead, buffer) {
callWithHttpCatch(response, buffer.dontTryThisAtHome()); // causes exception
response.end(buffer);
}); //fs.read
}); //fs.open
I know that probably isn't the answer you were looking for, but one of the nice things about ECMAScript (or functional programming in general) is how easily you can roll your own tooling for things like this.
At the time of this writing, the approach I am seeing is to use "Promises".
http://howtonode.org/promises
https://www.promisejs.org/
These allow code and callbacks to be structured well for error management and also makes it more readable.
It primarily uses the .then() function.
someFunction().then(success_callback_func, failed_callback_func);
Here's a basic example:
var SomeModule = require('someModule');
var success = function (ret) {
console.log('>>>>>>>> Success!');
}
var failed = function (err) {
if (err instanceof SomeModule.errorName) {
// Note: I've often seen the error definitions in SomeModule.errors.ErrorName
console.log("FOUND SPECIFIC ERROR");
}
console.log('>>>>>>>> FAILED!');
}
someFunction().then(success, failed);
console.log("This line with appear instantly, since the last function was asynchronous.");
Two things have really helped me solve this problem in my code.
The 'longjohn' module, which lets you see the full stack trace (across multiple asyncronous callbacks).
A simple closure technique to keep exceptions within the standard callback(err, data) idiom (shown here in CoffeeScript).
ferry_errors = (callback, f) ->
return (a...) ->
try f(a...)
catch err
callback(err)
Now you can wrap unsafe code, and your callbacks all handle errors the same way: by checking the error argument.
I've recently created a simple abstraction named WaitFor to call async functions in sync mode (based on Fibers): https://github.com/luciotato/waitfor
It's too new to be "rock solid".
using wait.for you can use async function as if they were sync, without blocking node's event loop. It's almost the same you're used to:
var wait=require('wait.for');
function handleRequest(request, response) {
//launch fiber, keep node spinning
wait.launchFiber(handleinFiber,request, response);
}
function handleInFiber(request, response) {
try {
if (request.url=="whatever")
handleWhateverRequest(request, response);
else
throw new Error("404 not found");
} catch (e) {
response.writeHead(500, {'Content-Type': 'text/plain'});
response.end("Server error: "+e.message);
}
}
function handleWhateverRequest(request, response, callback) {
if (something)
throw new Error("something bad happened");
Response.end("OK");
}
Since you're in a fiber, you can program sequentially, "blocking the fiber", but not node's event loop.
The other example:
var sys = require('sys'),
fs = require('fs'),
wait = require('wait.for');
require("http").createServer( function(req,res){
wait.launchFiber(handleRequest,req,res) //handle in a fiber
).listen(8124);
function handleRequest(request, response) {
try {
var fd=wait.for(fs.open,"/proc/cpuinfo", "r");
console.log("File open.");
var buffer = new require('buffer').Buffer(10);
var bytesRead=wait.for(fs.read,fd, buffer, 0, 10, null);
buffer.dontTryThisAtHome(); // causes exception
response.end(buffer);
}
catch(err) {
response.end('ERROR: '+err.message);
}
}
As you can see, I used wait.for to call node's async functions in sync mode,
without (visible) callbacks, so I can have all the code inside one try-catch block.
wait.for will throw an exception if any of the async functions returns err!==null
more info at https://github.com/luciotato/waitfor
Also in synchronous multi-threaded programming (e.g. .NET, Java, PHP) you can't return any meaningful information to the client when a custom unkown Exception is caught. You may just return HTTP 500 when you have no info regarding the Exception.
Thus, the 'secret' lies in filling a descriptive Error object, this way your error handler can map from the meaningful error to the right HTTP status + optionally a descriptive result. However you must also catch the exception before it arrives to process.on('uncaughtException'):
Step1: Define a meaningful error object
function appError(errorCode, description, isOperational) {
Error.call(this);
Error.captureStackTrace(this);
this.errorCode = errorCode;
//...other properties assigned here
};
appError.prototype.__proto__ = Error.prototype;
module.exports.appError = appError;
Step2: When throwing an Exception, fill it with properties (see step 1) that allows the handler to convert it to meannigul HTTP result:
throw new appError(errorManagement.commonErrors.resourceNotFound, "further explanation", true)
Step3: When invoking some potentially dangerous code, catch errors and re-throw that error while filling additional contextual properties within the Error object
Step4: You must catch the exception during the request handling. This is easier if you use some leading promises library (BlueBird is great) which allows you to catch async errors. If you can't use promises than any built-in NODE library will return errors in callback.
Step5: Now that your error is caught and contains descriptive information about what happens, you only need to map it to meaningful HTTP response. The nice part here is that you may have a centralized, single error handler that gets all the errors and map these to HTTP response:
//this specific example is using Express framework
res.status(getErrorHTTPCode(error))
function getErrorHTTPCode(error)
{
if(error.errorCode == commonErrors.InvalidInput)
return 400;
else if...
}
You may other related best practices here