I'm using defiantjs to perform json searches.
result = JSON.search(data, '//*[name="Gheorghe"]');
If the value is not found in the json I get an error Cannot read property 'Gheorghe' of undefined.
Is there a way to return something else if no search string is matched?
try {
//check for return value (search result or falsy value)
result = JSON.search(data, '//*searchValue') || 'not found';
} catch (e) {
//if there was an error in the request
console.log(e);
result = 'Not found. But dude, we could not even finish your request, as we encountered the following error: ' + e;
}
You can use try-catch statement
The try...catch statement marks a block of statements to try, and specifies a response, should an exception be thrown.
Example
In the following example, code in the try block can potentially throw three exceptions: TypeError, RangeError, and EvalError (Error types: EvalError, InternalError, RangeError, ReferenceError, SyntaxError, TypeError, URIError). When an exception occurs, control transfers to the appropriate catch clause. If the exception is not one of the specified exceptions and an unconditional catch clause is found, control transfers to that catch clause.
var result;
try{
alert(result.id);
} catch (e) {
if (e instanceof TypeError) {
// statements to handle TypeError exceptions
e='This is my custom type-error message instead of "Cannot read property..."';
} else if (e instanceof RangeError) {
// statements to handle RangeError exceptions
e='This is my custom range-error message instead of "Cannot read property..."';
} else if (e instanceof EvalError) {
// statements to handle EvalError exceptions
e='This is my custom eval-error message instead of "Cannot read property..."';
} else {
// statements to handle any unspecified exceptions
e='This is my custom unspecified-error message instead of "Cannot read property..."';
}
console.log("Error!",e); // prints to console custom error message
}
alert(result.id); // prints to console default error message result is undefined
Why can't you use
if(typeof(JSON.search(data, '//*[name="Gheorghe"]')) !== 'undefined') {
result = JSON.search(data, '//*[name="Gheorghe"]');
}
else {
//something else
}
Defiant.js, the third party library is supposed to take care of this issue. I take your word that they are not.
In that case, there are two ways to solve this issue.
To modify the library to return undefined when no results are found - this way is not recommended as it will be problematic to other developers who are working on the code base and also to maintain versioning of the library using bower/npm.
To use try catch around the implementation - this is the ideal way to solve this problem as you don't have to make changes to the third party library and you can get an easy trigger to check if the error from the try block is equal to "Cannot read property 'Gheorghe' of undefined", you can run your preferred callback.
This is the solution I would recommend.
var name = "Gheorge";
try {
result = JSON.search(data, '//*[name="' + name + '"]');
}
catch (error === "Cannot read property '" + name + "' of undefined") {
// As there could be any type of error from the function JSON.search
console.log(error);
yourErrorHandler(error);
}
Related
please help.
I'm making use of the node-mysql2 library
I have SQL queries and whenever a query is run and some variables are null in that query it triggers this error. This is usually when the session variables are null. AgentID=Null or DealerID=Null.
The error originates from the mysql2 connection.js file
C:\inetpub\wwwroot\pavstockallocatebot\node_modules\mysql2\lib\connection.js:538
if (sql.constructor === Commands.Query) {
^
TypeError: Cannot read properties of undefined (reading 'constructor')
Where it is triggered:
query(sql, values, cb) {
let cmdQuery;
if (sql.constructor === Commands.Query) {
cmdQuery = sql;
} else {
cmdQuery = Connection.createQuery(sql, values, cb, this.config);
}
this._resolveNamedPlaceholders(cmdQuery);
const rawSql = this.format(cmdQuery.sql, cmdQuery.values !== undefined ? cmdQuery.values : []);
cmdQuery.sql = rawSql;
return this.addCommand(cmdQuery);
}
It freezes my whole app. and doesn't allow me to restart the app.
How can I add an error handler that will check if the variables are undefined or null to avoid ever getting this error. When I do get this error to handle it appropriately.
There are many coding styles, but this is one solution.
It's crashing the app because it is an "uncaught" error. So let's catch it.
try {
//this will error
if (sql.constructor === Commands.Query) {}
} catch(error) {
// then you can console.log the error here
// and do something else.
}
Ideally you would check to see if sql is truthy and that your sql connection has been established before any sort of logic can touch this part of the code. But that can evolve into a bigger conversation around scaffolding and server logic architecture.
Check if this helps
if(sql && sql.constructor === Commands.Query)
or
if(sql?.constructor === Commands.Query)
I've seen both:
throw new Error(error);
&
console.error(error);
E.G:
jQuery:
if ( !w.document ) {
throw new Error( "jQuery requires a window with a document" );
}
&
Vue.js:
if (config.warnHandler) {
config.warnHandler.call(null, msg, vm, trace);
} else if (hasConsole && (!config.silent)) {
console.error(("[Vue warn]: " + msg + trace));
}
Both error handling ways seem reliable and used. But my question is:
Is there a difference between them? And if there is, when should I use which?
The key difference: throwing halts the execution, while console.error does not.
Most of the time, it's better to throw an error.
That's a built-in way to signal that something failed and normal execution cannot continue unless the error is expected, caught and handled properly.
In the most platforms, an uncaught exception will be logged to the console as well to warn the developer about it, but caught exceptions won't be logged, since they are assumed to be handled by the code.
Using console.error can be good for cases where the error happened isn't fatal, but you'd like to warn the developer.
However, overusing this feature can easily cause other errors and harder-to-debug code. For example, consider this code:
const elem = document.querySelector('.elem')
if(!elem)
console.error('elem cannot be found!')
const returnValue = functionThatDoesSomethingWithElem(elem)
if(!returnValue.success)
console.error('Doing something with elem has failed!')
if(!returnValue.doSomethingElse())
console.error('Doing something else with elem has failed!')
The above code will log three errors if there's no elem, but execution still continues, maybe causing even more errors.
By throwing an exception, this is avoidable:
const elem = document.querySelector('.elem')
if(!elem)
throw new Error('elem cannot be found!')
const returnValue = functionThatDoesSomethingWithElem(elem)
if(!returnValue.success)
throw new Error('Doing something with elem has failed!')
if(!returnValue.doSomethingElse())
throw new Error('Doing something else with elem has failed!')
This will print only the first error message, and execution halts, unless you put it inside a try..catch structure, like:
try{
const elem = document.querySelector('.elem')
if(!elem)
throw new Error('elem cannot be found!')
const returnValue = functionThatDoesSomethingWithElem(elem)
if(!returnValue.success)
throw new Error('Doing something with elem has failed!')
if(!returnValue.doSomethingElse())
throw new Error('Doing something else with elem has failed!')
}catch(exception){
console.error(exception)
fallbackMethod()
}
There's another difference: thrown errors can be caught by the caller of your function, so it can programmatically handle them (causing the execution to continue, and the error isn't displayed). On the other hand, if you use console.error, the caller can not decide if an error is expected, causing to log the error even if it is normal, so the console can become messy (you can't decide what's a real error and what's not.
Those two are completely different, let's see documentation of each one:
console.error:
Outputs an error message to the Web Console.
Throw:
throws a user-defined exception. Execution of the current function
will stop (the statements after throw won't be executed), and control
will be passed to the first catch block in the call stack. If no catch
block exists among caller functions, the program will terminate.
So, as you can see, they work differently, you can use both in your code, so keep in mind that just a console.error will probably pass unseen by the user, only those with console open will see the message, while throw will be noted, since everything will stop.
Let's see some functional examples:
console.error
Note that the "custom" error will show on console, but code stills executing, you only see the error message because console is showing here in stackOverflow. To stop execution you would need a return right after the console.error
function changeString(currentString, append) {
if (typeof append != 'string') {
console.error("Cannot change string!");
}
//THIS PART BELOW WILL EXECUTE, even with error logged
console.log(currentString + append);
}
changeString("I will show up even with error logged ", null)
Throw
Note that code stops execution when error is thrown and also the message of the error is different from the one that console.error shows.
function changeString(currentString, append){
if (typeof append != 'string'){
throw new Error("Cannot change string!");
}
//THIS PART BELOW WONT EXECUTE
console.log(currentString + append);
}
changeString("I wont show up in the console", null)
Here I added a try/catch, note the catch block being executed, this way I have control over the error and what should happen after the error being thrown, also, I mixed both: Throw and console.error
function changeString(currentString, append) {
try {
if (typeof append != 'string') {
throw new Error("Cannot change string!");
}
console.log(currentString + append);
} catch (er){
console.error("I'm being logged from inside a catch block because an error was thrown");
//DO WHATEVER YOU NEED TO FIX THE ERROR AND ALERT THE USER HERE
}
}
changeString("I wont show up in the console", null)
Further read on official documentations:
Throw
console.error
I would not consider them to be interchangeable. Console.error() simply logs your error to the console with special formatting.
When you actually throw an error you are essentially terminating execution unless you catch the error using a try catch block or some other form of error handling.
Why not have both, like this:
throw new ConsoleError('bad thing');
Source:
// based on https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error
class ConsoleError extends Error {
constructor(...args) {
const returnValue = super(...args);
console.error(...args);
// Maintains proper stack trace for where our error was thrown (only available on V8)
if (Error.captureStackTrace) {
Error.captureStackTrace(this, ConsoleError);
}
this.name = 'ConsoleError';
this.message = args[0];
// Pass remaining arguments (including vendor specific ones) to parent constructor
return returnValue;
}
}
window.ConsoleError = ConsoleError;
You may also want show the user when some errors happen, for this, use
// this to avoid crashing:
window.toastError('nice user error message', 'extra developer data:', someObject)
// this to crash:
throw new ToastError('we made a mistake')
Source:
window.toastError = (userMsg, ...developerDebugArgs) => {
// TODO: implement toast notifications
// only use userMsg for the toast notification
// Using DOMPurify and rendering userMsg as (potential) html may be nice,
// but backend team may prefer to simple return plain text instead of html
// may need to de-dupe messages being sent to toast component
console.log(
`%c${userMsg}`,
'color: orangered;font-style:italic;',
...developerDebugArgs
);
};
class ToastError extends Error {
constructor(...args) {
const returnValue = super(...args);
window.toastError(...args);
// Maintains proper stack trace for where our error was thrown (only available on V8)
if (Error.captureStackTrace) {
Error.captureStackTrace(this, ToastError);
}
this.name = 'ToastError';
this.message = args[0];
// Pass remaining arguments (including vendor specific ones) to parent constructor
return returnValue;
}
}
window.ToastError = ToastError;
You could also rename the ToastError class ToastException instead, if it suits your fancy
Is there a way to 'whitelist' - or prevent - specific errors from being thrown in a try catch block?
For instance, say I have an exception that I know about and don't want to log. However, I want to catch any other errors that pop up in that try/catch block.
This is the best that I can come up with:
try {
...
} catch(exception) {
//Loop through a predefined list of known errors that we want to ignore.
for (var i in whitelistOfErrors) {
//if our exception MATCHES an error that we want to ignore,
//don't throw it
if (exception == whitelistOfErrors[i])
break;
//if our exception DOESN'T MATCH an error that we want to ignore,
//throw it
if (i = whitelistOfErrors.length)
throw exception;
}
}
(or replace the logic with a method that searches the array for you, if that exists)
i'm tryin to identify the error i get in a javascrip function in my webpage, so i added
function guardarMisDatos() throws Exception {
try{
...
} catch (Exception e){
alert("error: ", e);
}
but when i open the page, the chrome web console gives me error at
function guardarMisDatos() throws Exception {
and the error type is "Uncaught syntaxerror: unexpected identifier"
where is the error? is it a correct way to check way the function is not fired on the first click?
It is JavaScript not Java. Lose the throws Exception!
Your code looks a lot like Java, not javaScript. The syntax for try/catch in javaScript goes like this:
try {
// do stuff
} catch (e) {
// something bad happened
}
Notice there is no throws and no type on e (since javascript is loosely typed)
Remove "throws Exception" and the catch reference to "Exception". To know what kind of exception it is, look at the e.name property, it'll be one of six things:
EvalError - An error in the eval() function has occurred.
RangeError - ut of range number value has occurred.
ReferenceError - An illegal reference has occurred.
SyntaxError - A syntax error within code inside the eval() function has occurred. All other syntax errors are not caught by try/catch/finally, and will trigger the default browser error message associated with the error. To catch actual syntax errors, you may use the onerror event.
TypeError - An error in the expected variable type has occurred.
URIError - An error when encoding or decoding the URI has occurred (ie: when calling encodeURI()).
These aren't constants, they're the actual string, as in if (e.name.toString()=="TypeError") There are a lot of other good things on the error object too, read more at http://www.javascriptkit.com/javatutors/trycatch2.shtml
Remove the throws Exception from your function definition. You do not need this in JavaScript. Besides that, why would your function ever throw an exception - you already catch it!
UPDATE
[Rewriting question to focus on the problem I am trying to understand.]
Is there a means in JavaScript to throw Exceptions that notify the line number where the problem occurs? Similar to C#'s debugger, if an error is thrown on line 50 then I will be taken to line 50.
For example, according to MDN EvalError represents an error with eval(). So, let's say I have a function that uses eval(). I want to use a specific error that is representative of the problem at hand, EvalError:
//As written here the error implies there is a problem on this line. See Firebug console window
var evalErra = new EvalError('required element missing from evaluation');
var stringFunc = "a=2;y=3;document.write(x*y);";
EvalString(stringFunc);
function EvalString(stringObject) {
//Some arbitrary check, for arguments sake let's say checking for 'x' makes this eval() valid.
if(stringObject.indexOf('x') !== -1) {
throw evalErra;
//throw 'required element missing from evaluation';//This way offers no line number
}
eval(stringFunc);//The problem really lies in the context of this function.
}
If I'm going about this all wrong, then please tell me how I should approach these kinds of issues.
When you throw an error, execution of the current code will stop and JS will work its way back up the execution tree until it finds a catch () which handles the particular type of error being thrown, or gets all the way up to the top of the tree, causing an "unhandled exception" error: You threw an error, and nothing caught it, and now someone's window got broken.
try {
if (true) {
throw 'yup'
}
} catch (e) { // catches all errors
... handle the error
}
When doing error handling you want to do the following
throw new Error("message");
Then if you ever handle this error look at err.stack (firefox/opera/chrome) or err.line (Safari) or err.IE_Y_U_NO_SHOW_ME_ERROR_LINE_NUMBER (IE) to find the line number.
If you want you can subclass Error.