I'm trying to loop through an enmap, but it doesn't seem to be working. I got forEach() to work, however, I need to be able to break out of it, which doesn't work with forEach(). Here's what I currently have
for(var id in bot.myenmap.fetchEverything()) {
console.log("test")
}
I have no other details as I can provide, as it doesn't error or log anything. If you know how to loop over it, any help would be appreciated, thanks.
If you got forEach() to work, you may want to check this answer: it explains how to "break" out of a forEach() loop.
You have to put the loop inside a try block, when you want to break the loop you can throw a custom exception: in the catch statement you'll make it ignore your custom exceptions, while throwing the ones that you didn't plan (like it normally would). Here's an example:
// This is to declare the custom exception:
var BreakException = {};
try {
bot.myenmap.forEach((element) => {
// This is like a normal forEach loop
// When you want to break it, just do this:
throw BreakException;
});
} catch (e) {
// If it's a BreakException it will ignore it and not givce errors
if (e !== BreakException) throw e;
}
Code adapted from the answer mentioned above.
Related
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 trying to build a catch try to execute some javascript code. NO JQUERY I want to identify if a div id ('test') exists and if it doesn't don't execute the code. How would I do this? I know the structure of a try catch is
try{
}
catch(e){
}
use try-catch as less as possible: just check whether or not the DOM element exists:
if (document.getElementById('test')!=null) {
// element (div) with id 'test' exists
}
else {
// it doesn't
}
I would make things simpler and use if instead of try-catch. try-catch is designed for exceptional situations, when you really don't know what to do throw an error. Throwing an error causes the whole code block to terminate it's execution.
I would do like this:
var divId = 'test';
if (document.getElementById(divId)) {
alert('exists');
} else {
alert('does not exist');
}
There is no need to check document.getElementById() result on null (in all modern browsers null is returned when no element is found). In most JavaScript projects developers skip typing !== null since null is treated as false and DOM object is treated as true, so programmers avoid typing obvious things.
This may be a bad question, but I've noticed that as I'm writing coding along using mootools When I've got some code that goes through callbacks, bindings and generally isn't just a straight forward function call, if there's an error it doesn't get picked up by either Firebug or Chrome's console it just silently fails, and I'm forced to track down the error using trys and such that don't give you handy information like the line of code that's failing. It's like writing code for IE6 all you have to go on is some opaque message like 'can not read 'x' of undefined.'
I realize that the question isn't specific enough to ask 'how do I avoid this' but does anyone else run into this problem and if so how do you work around it? I'm also a little confused how an error could be picked up by a try/catch block, but not the javascript console.
EDIT:
OK, I've come up with something that reproduces the error
say you've got a function
function foo(){
var x = value.blah;
}
if I call that function like foo() I rightly get an reference error in my console. If, however, I call it like
(function(){
foo.attempt();
})()
I get no error in the console, but if I change foo to be
function foo(){
try{
var x = value.blah;
} catch(e){console.log(e)}
}
the console will log e but of course without the handle 'line: whatever' information.
I have considerable experience fiddling with errors in JavaScript. I've mostly used Chrome for building my understanding but most of it applies to Firefox and Internet Explorer as well.
I can immediately debunk your assumption about silent JavaScript errors. They don't exist, Errors always show. There might be a bug in Firefox or the Chrome's webdev, but the errors are there.
The most common way for errors not to show up is because you're catching them yourself. Perhaps prematurely.
I've figured out what I think is the best strategy for catching errors:
1. Always throw things that are Errors or inherited from Errors.
Ex: not: throw "Precondition failed" but throw new Error("Precondition failed").
This is because Errors are weird in JavaScript (I have no other word for it). If you want a stacktrace (and heaven's yes you want a stacktrace) you'll need to throw an Error (and not a string).
2. Don't use window.onerror Not much to say here. It's useless. You have no control over what get's flung to this function. It might be your code, it might be a broken plugin that a visitor uses. Also, no stacktrace.
3. Have one (global) error handler / when to catch errors
JavaScript is event driven. This has some unexpected consequences. Observe the following code:
try {
setTimeout(function () {
throw new Error("nope! :D");
}, 1);
} catch (e) {
console.log(e);
}
You will not see this error. (Firebug / console will catch it though)
This is because the inner function runs in it's own event and the try-catch statement no longer applies to it. The correct way is:
try {
setTimeout(function () {
try {
throw new Error("nope! :D");
} catch (e) {
console.log("Hell yea!", e);
}
}, 1);
} catch (e) {
console.log(e);
}
Or just make a function that wraps a function in a try-catch:
function wrap(wrap_dat_func) {
return function () {
try {
wrap_dat_func.apply(wrap_dat_func, arguments);
} catch (e) {
// send to error handler
}
}
}
Use like:
setTimeout(wrap(function () {
// etc
}), 1);
So basically whenever you generate a new event, wrap the callback in your global try catch function. So wrap call to setTimeout, setInterval all DOM related events like onclick onload ondocumentready, also AJAX calls onreadystatechanged.
How to get proper stacktraces (over events!) is another long winded explanation.
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.
I'm writing quite a bit of code in Prototype.js which returns null if a DOM-id wasn't found.
$("someId").show();
If someId doesn't exist, a method will be called on null, which halts the entire program, in effect disabling all JS effects after the error. I could just check for null before executing such a statement, but this is getting tiring.
I would like to catch an exception but I'm not sure which one its is. MDC lists the following ECMA Script error types, but on first glance none of them seem to be what I want:
* Error
* EvalError
* RangeError
* ReferenceError
* SyntaxError
* TypeError
* URIError
* DOMException
* EventException
* RangeException
Also, do browsers have a unified way of dealing with a method call on null?
I don't believe there's unity to be found. Chrome throws a TypeError, but IE throws an Error, so you would probably have to catch everything and make severe assumptions. Better to check for null first.
var element = $('someId');
if (element) {
element.show();
// whatever else...
}
If element.show() is the only thing you need it for, then it can obviously be written a lot shorter, but in most cases that would be appropriate.
The correct way to handle this is to check for null before doing something with an object. There are several shorthand ways to do this, the shortest is (as Alex K) wrote
$("someId") && $("someId").show();
but this seems to me to be harder to read.
To answer your question directly you can do
try { $('someId').show(); } catch (e) {}
but this seems amateurish. You should program explicitly because later on someone else won't know why you wrote that odd code. The first example is slightly opaque but at least contains the null test first, and doesn't hide errors in the show() method.
Incidentally, if you were using JQuery instead of Prototype, this code would work without error even if there is no object with id 'someId':
$('#someId').show()
That's because the $() function in JQuery returns a collection which may be empty but is never null.
If your going to chain .show() on $("someId") then check its result first.
if ($("someId"))
$("someId").show();
or
$("someId") && $("someId").show();
or
if (someVar = $("someId"))
someVar.show();
If for some reason you really need to identify them you could wrap $() and throw a custom exception:
function NullReferenceException(id) {this.id = id}
function $my(id) {
var el = $(id);
if (!el)
throw new NullReferenceException(id);
return el
}
try {
$my("iDontExistId").show();
} catch (e) {
if (e instanceof NullReferenceException)
alert(e.id + " doesn't exist");
}
Just ignore which exception it is...
try
{
null.hey()
}
catch(e)
{
//handle it here
}