I am intending to use node.js FileSystem realpathSync()
to determine the real path of a file. Does realpathSync()
also check whether the file exists. Is it enough to do:
try {
res = fs.realpathSync(path);
} catch (err) {
/* file does not exist or some other I/O error */
}
Or should I also to:
if (!fs.existsSync(res)) {
/* file does not exist */
}
If yes, is existsSync() free of I/O errors, or does it possibly also
throw some error? In either case, concerning the thrown error err,
how can I divide apart existence error from other I/O errors?
realpathSync() does indeed throw an error in case the file or directory doesn't exist. But a nifty detail, err.code is a string and not some number. So I went with the following solution:
try {
res = fs.realpathSync(path);
} catch (err) {
if (err.code === "ENOENT") {
/* file or directory does not exist */
} else {
/* some other I/O error */
}
}
Related
I'm currently building an application for file backup, and it got quite a bit of reading and writing to the filesystem. Most of it works great, but I'm struggling a bit with the error handling of the app.
In the screenshot below the last path is not a valid directory and return an exception as you can see.
function getTotalSize(pathToDir, dir) {
fs.readdir(pathToDir, function(err, files) {
if (err) {
// handle my error here
throw new Error('something bad happened');
return;
}
// continue if no errors :)
My question is, is it possible to replace the standard error window with my own? Or in some cases ignore the pop up of the error window? First time working with Electron so sorry if this is an obvious one.
Thanks!
When you throw the error from readdir it gets caught by the top-level uncaughtException handler, indicated by the the first line: "Uncaught Exception".
What you need to do is add your own custom handler for the uncaughtException in your main process and show whatever dialog you want from there.
Take a look at the dialog module.
As an example, you can use the dialog.showMessageBox method to configure all sorts of things about the error dialog like this:
process.on("uncaughtException", (err) => {
const messageBoxOptions = {
type: "error",
title: "Error in Main process",
message: "Something failed"
};
dialog.showMessageBoxSync(messageBoxOptions);
// I believe it used to be the case that doing a "throw err;" here would
// terminate the process, but now it appears that you have to use's Electron's
// app module to exit (process.exit(1) seems to not terminate the process)
app.exit(1);
});
Here is my scenario:
I am creating a user object which I am saving to my database. After this I am doing something else which may result in an error. If so, I need to "rollback" the changes I made to the database, meaning I have to delete the user object from the database again in the catch block. However, this delete action may also fail meaning I need to know how I handle this?
When I say "handle" what I mean is I would like to save the error to my database. So I want the original error to be saved and also the error in the case the deleting fails. (I also know saving the error to the database might fail, but if it does there isnt much I can do so I'll just let it happen)
So do I need to use a nested try-catch inside the catch block? or will the catch block "catch" its own errors?
// psuedocode-ish illustation of what I'm working with
try {
const new_user = Database.save(user);
MoreCodeThatMightThrowAnError(); // imagine this throws an error
}
catch (error) {
if (new_user) Database.delete(user); // Do I need this inside a nested try-catch?
console.log(error);
Database.save(error); // dont care if this fails
}
Also, this is just a simplified example of what I am doing so I cannot just move the MoreCodeThatMightThrowAnError() up or use some build in rollback functionality from my database unfortunantly.
You are correct, you need to use another try-catch block. Even though it' seems a bit strange, it's sometimes unavoidable. See this question for more.
I would suggest organizing your code like this:
// psuedocode representation
try {
const new_user = Database.save(user);
try {
const otherCode = Database.otherThingThatCauseError();
} catch(err) {
console.log(err)
}
// ... and so on
} catch(err) {
// no need to rollback, most databases are ACID-compliant
console.log(err);
So basically, you would want to add another try, catch block. I believe that you won't have to rollback your changes since databases are ACID compliant, so if something wrong happens in the middle of an operation (i.e. creating a new user), the database will automatically roll back the whole operation.
A catch block does not catch errors that occur inside of it, so you would need to use a nested try...catch statement.
try {
const new_user = Database.save(user);
MoreCodeThatMightThrowAnError(); // imagine this throws an error
}
catch (error) {
console.log(error);
try {
if (new_user) Database.delete(user);
} catch (error2) {
console.log(error2);
try {
Database.save(error2);
} catch (error3) {}
}
}
I am new to Sentry and I want to log an error manually.
For some reason I am unable to find in their docs, how I can achieve this
I am using RN project but from their docs, RN extends JS sdk
Consider a function as simple as this
const logErrorIntentionally = () => {
try {
} catch (error) {
//throw sentry error here
}
}
How can I log thrown error in sentry? from my catch block.
According to the docs:
import * as Sentry from '#sentry/browser';
try {
aFunctionThatMightFail();
} catch (err) {
Sentry.captureException(err);
}
For custom messages:
import * as Sentry from '#sentry/browser';
Sentry.captureMessage("Something went wrong");
The most common form of capturing is to capture errors. What can be captured as an error varies by platform. In general, if you have something that looks like an exception, it can be captured. For some SDKs, you can also omit the argument to captureException and Sentry will attempt to capture the current exception. It is also useful for manual reporting of errors or messages to Sentry.
You can read more from the official docs https://docs.sentry.io/platforms/react-native/usage/
Is there a way to add a default behavior in javascript to the throw event.
Like I am trying to add to a file whenever an error is thrown :
Example :
if (tables.length === 0) {
throw new Error("NO_TABLES_RETRIEVED");
}
I want to write to file first and then throw the error. I know I can add a function and just before throwing I can call that function but just to know more is there something like to add a default behavior with throw?
Error is different from Exception in Javascript w.r.t NodeJS. An error is any instance of the Error class. Errors may be constructed and then passed directly to another function or thrown. When you throw an error, it becomes an exception.2 Here's an example of using an error as an exception:
throw new Error('something bad happened');
but you can just as well create an Error without throwing it:
callback(new Error('something bad happened'));
Since you mentioned in the comment that you don't want to require the error handler file in all the files of the app. You can also make use of NodeJS EventEmitter module or use a error handler middleware
I think your best bet is to use a custom throw. I actually always do it, to be able to write
_throw("MyErrorMessage")
So I would do something like that:
//Should use something like dot-env with the path to your errors
require('dotenv').config()
//I'm just gonna fake it to make it work on your machine:
process.env.error_file_path = './myErrors.txt'
//throwLib.js
const util = require('util')
const fs = require('fs')
const writeFile = util.promisify(fs.appendFile)
_throw = (stringError) => {
writeFile(process.env.error_file_path, "Error : " + stringError + "\n").then(err => {
if (err)
console.log(err)
throw new Error(stringError)
}
)
}
//import this in your files.
//myFile.js
//someStuff
_throw('someMessage1')
_throw('someMessage2')
_throw('someMessage3')
You can create your own custom error and do some logic in the constructor.
function MyError(){
//do some logic herer (e.g. write to file)
console.log("some logic");
}
throw new MyError()
If you are using a NodeJS application, you can centrally manage all your thrown errors.
You should also name your errors:
class ApiError extends Error {
constructor (message, code) {
super(message);
this.name = 'ApiError';
this.code = code;
}
}
Similarly use other names for other error types.
For an express application,
app.use(routes);
// place this after your routes in express app. This will catch all your thrown errors.
app.use(function (err, req, res, next) {
console.log(err);
switch (err.name) {
case 'ApiError':
// write to file here
return res.status(err.code || 500).send({error: err.message});
case 'Some other error':
// handle differently
break;
default:
res.status(err.status || 500).render('500', {error: err});
}
});
Note if you are throwing from within a Promise, async/await, this won't catch your error. You will have to catch them centrally some other way, possibly by catching all Unhandled Promise Rejections in your app
process.on('unhandledRejection', (reason) => {
console.log(reason);
// log error in file
});
Similarly, you should also catch all uncaught exceptions centrally
process.on('uncaughtException', (err) => {
console.log(err);
// log error in file
});
Suggestion:
As far as logging errors in file are concerned, it is a great way to do that only if you're parsing your file by some other way, sending your file to logstash etc.
When you're not planning to parse your file programmatically, log your errors in an errordb / error-table. They are much easier to query that way :)
I am trying to load some content using require.js. If the content doesn't exist I'd like to catch the error and notify the user.
In firebug I can see two errors:
"NetworkError: 404 Not Found
...and then a few seconds later:
var e = new Error(msg + '\nhttp://requirejs.org/docs/errors.html#
Load timeout for modules: modules/messages/messages
http://requirejs.org/docs/errors.html#timeout
My code resembles:
require([path], function(content){
//need to catch errors as this will not be called;
});
How would one bind to requirejs events? Any idea?
It is also possible to use errbacks to have customized error handling appropriate to the specific use of require. Errbacks are documented here http://requirejs.org/docs/api.html#errbacks. Basically, you can add to require a function to be called if the load fails. It comes right after the function to be called if the load is successful.
Chin's case could be handled as:
require([path], function(content){
//need to catch errors as this will not be called;
}, function (err) {
//display error to user
});
Here's an example that tries loading from multiple places:
require([mode_path], onload, function (err) {
if (mode_path.indexOf("/") !== -1)
// It is an actual path so don't try any further loading
throw new Error("can't load mode " + mode_path);
var path = "./modes/" + mode_path + "/" + mode_path;
require([path], onload,
function (err) {
require([path + "_mode"], onload);
});
});
In this example onload would be the function called once the required code loads, and mode_path is a string identifying the mode. What you see there is code attempting to load a mode module for an editor from 3 different locations. If mode_path is foo, it will try to load foo, then ./modes/foo/foo and then ./modes/foo/foo_mode.
The example at requirejs.org shows how one might handle a case where they want to try multiple locations for a resource they want to make available with a well-known identifier. Presumably the entire code-base in that example requires jQuery by requiring "jquery". Whatever location jQuery happens to be located at, it becomes available to the whole code-base as "jquery".
My example does not care about making the mode known to the entire code-base through a well-known identifier because in this specific case there's no good reason to do so. The onload function stores the module it gets into a variable and the rest of the code base gets it by calling a getMode() method.
set the requirejs onError function:
requirejs.onError = function (err) {
if (err.requireType === 'timeout') {
// tell user
alert("error: "+err);
} else {
throw err;
}
};
If you want to setup an event you could bind to and trigger a global object. Such as:
$("body").bind("moduleFail",function(){
alert("Handling Event")
});
requirejs.onError = function (err) {
if (err.requireType === 'timeout') {
$("body").trigger({type:"moduleFail",err:err})
} else {
throw err;
}
};
require(["foo"],function(foo){
alert("loaded foo" + foo)
})
Did you try to override the requirejs.onError like shown here?
It worked for me after setting catchError as true like this:
require.config({catchError:true});
before calling any define() or require() functions.
You can use the requirejs.onError function as :
requirejs.onError = function (err) {
if (err) {
//Reload
}
else {
throw err;
}
};
You can also use err.requireType to catch specific errors like timeouts