Where to CATCH an EXCEPTION thrown within an EVAL - javascript

The following script enables you to run a piece of javascript code. Errors are being catched by the try / catch block.
try {
var result = eval(script);
} catch (e) {
// do something meaningful
}
However, if the variable script contains for instance an AJAX call, and this ajax call throws an exception (e.g. in the success function), this exception will NOT be catched by this try / catch block...
// execute an AJAX request
var script = '$.ajax(url:"/somewhere", success: function(){throw new MyException('testexception')})';
try {
var result = eval(script);
} catch (e) {
// will not be triggered...
}
Question: how can I catch the exception thrown within the ajax request?

I hope you are aware of the dangers of using eval, and if not there are plenty of good articles out there that explain why it is not a good idea.
That being said, the issue is that the success callback is being called after the catch block. You'll need to either add the try/catch block within the success callback, or you'll need to handle the error from a more global perspective. One idea I can think of to do this is using the window.onerror event. I have an example below that shows something similar to your problem, and one that shows you can catch errors thrown in eval.
(function() {
'use strict';
window.addEventListener('error', e => console.log(`window.onerror: ${e.message}`));
let script = `setTimeout(function() {
throw new Error('Whoops!');
}, 0);`;
eval(script);
script = `throw new Error('Whoops!');`;
try {
eval(script);
} catch (e) {
console.log(e.message);
}
})();

Related

Sending handled (not just unhandled) Javascript errors to server

I'm trying to send ALL my Javascript exceptions, handled as well as unhandled ones, to server for logging. I've gone through window.onerror documentation and also this post that throws light on this issue, but they work best for unhandled exceptions only.
window.onerror does not fire if the exception is already handled in a catch() block.
One 'painful' way would be to attach my logToServer() function manually to every catch() block in my code (and it works too), but I'm hoping for a better solution.
I've set up a little snippet below.
var logToServer = function logToServer() {
console.info('logToServer() called');
};
window.onerror = function(z, x, c, v, b) {
console.info(z);
console.info(x);
console.info(c);
console.info(v);
console.info(b);
// call a function to send to server
logToServer();
};
window.addEventListener('error', function(z, x, c, v, b) {
console.info(z);
// call a function to send to server
logToServer();
});
// test w/o catch-block
//console.info(err); // calls logToServer()
// test w/ catch-block
try {
console.info(asd); // does not call logToServer()
} catch (err) {
console.error(err);
};
Enable logs in console.
window.onerror fires only when an exception is unhandled. If you catch any exception, this event wont fire. You will have to do it explicitly in all try--catch blocks. In catch block you will have to throw your exception. The syntax is simple:
try{
//Your try logic
}
catch(ex){
// Your catch logic comes here
throw ex; //This will throw exception and window.onerror will be fired.
}

Javascript - Where exactly to place try - catch?

Try catch is used to catch errors and report to user. all said and fine. But where exactly one has to put the try-catch. Or What exactly has to go inside try catch on a usual basis.
Most importantly, is it absolutely a good coding practice to have a try catch block?
I think it is good practce to use a try catch if it will handle errors and prevent the program from crashing.
Taken from W3 Schools:
The try statement lets you test a block of code for errors.
The catch statement lets you handle the error.
The throw statement lets you create custom errors.
The finally statement lets you execute
code, after try and catch, regardless of the result.
An example:
fuction foo()
{
try
{
// Block of code to try
}
catch(e)
{
// Block of code to handle errors
document.getElementById("demo").innerHTML = e.message;
}
finally
{
// Block of code to be executed regardless of the try / catch result
}
}
Here is soem more documentation at W3 Schools: http://www.w3schools.com/js/js_errors.asp
Yes, it absolutely good practice to use try-catch blocks. Here's a rather simplistic (but contrived) demonstration.
function safeParseJSON(json) {
try {
return JSON.parse(json);
} catch(exception) {
// could not parse this JSON
console.error(exception);
} finally {
return null;
}
}
Parsing JSON is the most common scenario I have encountered for using the try-catch construct, hence the example.
However, the usual try-catch mechanism doesn't work when the function is asynchronous. It's essential to understand this if you are ever using a server side Javascript platform.
The standard pattern for async event handling is as follows.
db.connect(options, function connected(err, client) {
if(err) throw err;
client.query(...);
});
Because that callback function is run somewhere else (presumably when the database connects) we can't wrap it with a try-catch block. Instead, most async method calls will pass the error as the first argument to the callback.
This way we can handle the error as and when it happens. If there is no error, null will be passed as the first argument, so that it can be ignored.
A number of implementations of promises try to recreate this mechanism, but in an asynchronous way.
Here's an example with Q:
db.connect(options)
.then(function(client) {
client.query(...);
})
.catch(function (error) {
throw error;
})
.fin(function() {
// finally
db.close();
});
You can also use Q on the client side, if you are working with asynchronous functions.

Catch statement does not catch thrown error

For some reason this code gives me an uncaught exception error. It seems the catch block is not catching the error. Are try catch blocks scoped in such a way that I cannot throw an error in a nested function, and then expect it to be caught by a catch statement scoped higher up the chain? Some of the sensitive data with in the application that i'm working in has been removed, but it expected that leadInfo[ 0 / 1] would be a 32 character alpha numeric string that I pull from URL parameters.
The underlying issue here is with my AJAX call returning an error from the API and that error not being handled properly within the application. Hence the need for the throw statement. The AJAX call completes fine, and returns a JSON object that does not contain the email address as a property, so I need to handle that in a way that changes the page to reflect that.
jQuery(document).ready(function(){
try {
url = "http://api.com/api/v1/lead/" + leadInfo[1]
jQuery.ajax({
type: 'GET',
contentType: 'application/json',
url: url,
dataType : 'jsonp',
success: function (result) {
result = jQuery.parseJSON(result);
if(!result.data.email){
throw ('New exception');
}
console.log(result);
jQuery('.email').html(result.data.email);
}
});
jQuery('.surveryButton').click(function(){
window.location.replace("http://" + pgInventory.host + pgInventory.path + leadInfo[0] + "&curLeadId=" + leadInfo[1] + "&curViewedPages=0");
});
}
catch(err) {
jQuery('.email').html('your e-mail address');
jQuery('#arrowContent').remove();
}
});
The reason why your try catch block is failing is because an ajax request is asynchronous. The try catch block will execute before the Ajax call and send the request itself, but the error is thrown when the result is returned, AT A LATER POINT IN TIME.
When the try catch block is executed, there is no error. When the error is thrown, there is no try catch. If you need try catch for ajax requests, always put ajax try catch blocks inside the success callback, NEVER outside of it.
Here's how you should do it:
success: function (result) {
try {
result = jQuery.parseJSON(result);
if (!result.data.email) {
throw ('New exception');
}
console.log(result);
jQuery('.email').html(result.data.email);
} catch (exception) {
console.error("bla");
};
}
Due to the asynchronous nature of the callback methods in javascript, the context of the function throwing the error is different compared to the original one. You should do this way:
success: function (result) {
try {
result = jQuery.parseJSON(result);
if(!result.data.email){
throw ('New exception');
}
console.log(result);
jQuery('.email').html(result.data.email);
}
catch(err) {
// Dealing with the error
}
}
I would suggest you to have a look at this excellent article about the (very particular) contexts, closures and bindings in Javascript.
The problem is that ajax is asynchronous by definition. Your exception does not get thrown from within the $.ajax function, but from the callback function on success (which is triggered at a later time).
You should give an error: function(data) {} parameter to it as well, to handle server response errors, and furthermore you should place the try/catch block inside the callback function.
If you really want to catch it outside the callback, then you should consider calling a function rather than throwing an exception, because I don't see how it can be done.

JavaScript catch Block with Wrong Context

I've got the following code:
try {
...
try {
// This is *never* called
alert('TRY');
} catch (e) {
// But this *is* called
alert('CATCH');
}
} catch (e2) {
...
}
The problem is, the alert from the inner catch block is executed but not the one from the inner try.
Is this possible at all per specification or does anyone have an idea what is happening here ?
Can an exception from e.g. asynchronous code run into the context of another catch block ?
Note this is real code I put in there, no omissions in the inner try / catch !
Some asynchronous code may be run before entering the block.
This is from code taken from a web app running in WebKit / QtWebKit from PyQt 4.9.0 and Qt 4.8.0.
Ok, so here some more code before the inner try/catch (where the first ellipsis is):
DoSomething(function () {
var updatePromises = [];
var p;
for (...) {
p = new Promise();
updatePromises.push(p);
// Run asynchronous code to fulfill promise.
// Calls are chained using an array and a "setTimeout()" mechanism.
tasks.chain(function (promise) { ... }, this, p);
}
(function () {
...
}).future().apply(this, updatePromises);
}.bind(this));
The ES5 specification says the following (emphasis added):
The try statement encloses a block of code in which an exceptional
condition can occur, such as a runtime error or a throw statement. The
catch clause provides the exception-handling code.
...
The production TryStatement : try Block Catch is evaluated as follows:
Let B be the result of evaluating Block.
If B.type is not throw, return B.
Return the result of evaluating Catch with parameter B.
My understanding of that is that, according to the spec, there is no way a catch block can be executed without first evaluating the try block.
I think the answer is no, based on the mozilla reference. I recommend you log each time a block is entered and exited, and see if there is any weird stuff going on that you missed. Maybe use debugger; too.
Or try this perhaps:
var foo = false;
try {
try {
foo = true;
throw true;
} catch (e) {
if(foo) {
alert('CATCH');
} else {
alert('HUH?');
}
}
} catch (e2) {
alert('CATCH2');
}

Is try {} without catch {} possible in JavaScript?

I have a number of functions which either return something or throw an error. In a main function, I call each of these, and would like to return the value returned by each function, or go on to the second function if the first functions throws an error.
So basically what I currently have is:
function testAll() {
try { return func1(); } catch(e) {}
try { return func2(); } catch(e) {} // If func1 throws error, try func2
try { return func3(); } catch(e) {} // If func2 throws error, try func3
}
But actually I'd like to only try to return it (i.e. if it doesn't throw an error). I do not need the catch block. However, code like try {} fails because it is missing an (unused) catch {} block.
I put an example on jsFiddle.
So, is there any way to have those catch blocks removed whilst achieving the same effect?
A try without a catch clause sends its error to the next higher catch, or the window, if there is no catch defined within that try.
If you do not have a catch, a try expression requires a finally clause.
try {
// whatever;
} finally {
// always runs
}
It's possible to have an empty catch block, without an error variable, starting with ES2019. This is called optional catch binding and was implemented in V8 v6.6, released in June 2018. The feature has been available since Node 10, Chrome 66, Firefox 58, Opera 53 and Safari 11.1.
The syntax is shown below:
try {
throw new Error("This won't show anything");
} catch { };
You still need a catch block, but it can be empty and you don't need to pass any variable. If you don't want a catch block at all, you can use the try/finally, but note that it won't swallow errors as an empty catch does.
try {
throw new Error("This WILL get logged");
} finally {
console.log("This syntax does not swallow errors");
}
Nope, catch (or finally) is try's friend and always there as part of try/catch.
However, it is perfectly valid to have them empty, like in your example.
In the comments in your example code (If func1 throws error, try func2), it would seem that what you really want to do is call the next function inside of the catch block of the previous.
I wouldn't recommend try-finally without the catch, because if both the try block and finally block throw errors, the error thrown in the finally clause gets bubbled up and the try block's error is ignored, in my own test:
try {
console.log('about to error, guys!');
throw new Error('eat me!');
} finally {
console.log ('finally, who cares');
throw new Error('finally error');
}
Result:
> about to error, guys!
> finally, who cares
> .../error.js:9
> throw new Error('finally error');
> ^
>
> Error: finally error
No, it is not possible to have try block without catch (or finally). As a workaround, I believe you might want to define a helper function such as this:
function tryIt(fn, ...args) {
try {
return fn(...args);
} catch {}
}
and use it like:
tryIt(function1, /* args if any */);
tryIt(function2, /* args if any */);
I've decide to look at the problem presented from a different angle.
I've been able to determine a way to to allow closely for the code pattern requested while in part addressing the un-handled error object listed by another commenter.
code can be seen # http://jsfiddle.net/Abyssoft/RC7Nw/4/
try:catch is placed within a for loop allowing graceful fall through. while being able to iterate through all the functions needed. when explicit error handling is needed additional function array is used. in the even of error and functional array with error handlers element is not a function, error is dumped to console.
Per requirements of stackoverflow here is the code inline [edited to make JSLint compliant (remove leading spaces to confirm), improve readability]
function func1() {"use strict"; throw "I don't return anything"; }
function func2() {"use strict"; return 123; }
function func3() {"use strict"; throw "I don't return anything"; }
// ctr = Code to Run <array>, values = values <array>,
// eh = error code can be blank.
// ctr and params should match 1 <-> 1
// Data validation not done here simple POC
function testAll(ctr, values, eh) {
"use strict";
var cb; // cb = code block counter
for (cb in ctr) {
if (ctr.hasOwnProperty(cb)) {
try {
return ctr[cb](values[cb]);
} catch (e) {
if (typeof eh[cb] === "function") {
eh[cb](e);
} else {
//error intentionally/accidentially ignored
console.log(e);
}
}
}
}
return false;
}
window.alert(testAll([func1, func2, func3], [], []));
​
If you only want functions 2 and 3 to fire if an error occurs why are you not putting them in the catch block?
function testAll() {
try {
return func1();
} catch(e) {
try {
return func2();
} catch(e) {
try {
return func3();
} catch(e) {
// LOG EVERYTHING FAILED
}
}
}
}
...is there any way to have those catch blocks removed whilst achieving the same effect? As it would seem, no; Javascript requires a try block be followed by either a catch or a finally block.
Having said that, there is a way to use those catch blocks to achieve the effect you want.
// If func1 throws error, try func2 The if throws error condition, is what the catch block is for.
Why remove them when their use is exactly what you are after?
try { return func1(); }
catch {
// if func1 throws error
try { return func2(); }
catch {
// if func2 throws error
try { return func3(); }
catch {
// if func3 throws error
}
}
}
I completely understand why you might not need a catch block, and would find it cleaner to be able to omit it entirely. But I don't think this is one of those situations.
They go together in every language that I know that has them (JavaScript, Java, C#, C++). Don't do it.
Since ES2019 you can easily use try {} without catch {}:
try {
parseResult = JSON.parse(potentiallyMalformedJSON);
} catch (unused) {}
For more info please reffer to Michael Ficcara's proposal
try & catch are like 2 side of one coin. so not possible without try.
No. You have to keep them.
This actually makes sense since errors shouldn't be silently ignored at all.

Categories