I try to simulate a problem where a script that is loaded from an external url stops execution of any more scripts on my site.
I tried to simulate such a problem by calling a function that does not exits. I can see the error in firebug but different scripts on the page are still executed.
Are there different kinds of errors in Javascripts? If yes: what kind of error stops script execution? I only need this answer for Firefox.
EDIT
This question is easy to misunderstood but Rob W got it: I need to throw an exception and that exception needs to stop further script execution.
Answer to the title: No
Answer to "Are there different kinds of errors in JavaScript**: Yes, see MDN: Error
Syntax errors will prevent a whole script block from being executed,
other errors (TypeErrors, Reference errors) will only stop the execution after the occurrence of the error.
Different <script> blocks are executed separately. You cannot prevent the second block from execution by throwing an error in the first block (Demo: http://jsfiddle.net/WJCEN/).
<script>Example: Syntax error in this script.</script>
<script>console.log('Still executed.')</script>
Also, if an error is caught using try-catch (demo: http://jsfiddle.net/WJCEN/1/), then the error will not even stop the execution a whole block.
try {throw 'Code';}catch(e){}
console.log('Still executed');
There is no general one-fit-all method to stop all code from running. For individual scripts, you can use some tricks to prevent the code from running further.
Example 1 (demo): Temporary overwrite a method
1: <script>window._alert = alert;alert=null;</script>
2: <script>alert('Some code!');confirm('Not executing');</script>
3: <script>alert=_alert;delete window._alert;alert('Done!');</script>
This method is based on the fact that script 2 expects alert to be a function. We have rewritten alert to a non-function property (script 1). Script 2 throws a TypeError, and the second block is skipped.
We restore the original values in script 3.
Example 2 (demo): Define a constant method, which cannot be overwritten.
4. <script>Object.defineProperty(window, 'test',{value:null});</script>
5. <script>var test=function(){alert('Test');};test();alert('What?');</script>
This methods relies on the Object.defineProperty method, to effectively define a constant value. In strict mode, the var test declaration would throw a TypeError: "test is read-only".
When strict mode is not enables, a TypeError will be thrown at test(): "test is not a function" (because we defined test to be constant, in script 4).
Note: The last method is not working correctly with function declarations (see bug #115452, Chrome 17)
Use
try catch finally block
It will do the trick
you can use the error object which support the following two properties:
name: The name of the error.
message: A description of the error.
for example to stop execution you can use : throw new Error("myError");
Are there different kinds of errors in Javascripts?
Besides the generic Error constructor, there are six other core errors in JavaScript:
see here details on these errors.
Stop the execution with
throw new Error('stopIt');
This will also do the trick:
throw 'Stop It!';
Related
I am wrapping my code into try/catch blocks and I decided to test it out to see how it works.
Below is a simple snippet of code that will generate a Syntax Error - trigge rHandler
try{
$(document).trigge rHandler('fbload');
}catch(e){
alert(e);
}
However I'm not getting the alert! Instead the error is logged in the console as an Unhandled Syntax Error. I was expecting that any error that is generated inside the Try block will automatically be passed down into the Catch section where I can do anything I want with it? Why does this not appear to be working?
try..catch will catch exceptions which occur at runtime. But Syntax errors occur during parsing time itself. So, when the code
$(document).trigge rHandler('fbload');
is encountered, JavaScript tries to parse the expression. But it couldn't. So it is clueless and fails immediately with SyntaxError and that is why it is not caught by the except block.
I noticed that qUnit doesn't give any notice when an exception happens in a later part of the test. For example, running this in a test():
stop();
function myfun(ed) {
console.log('resumed');
start(); //Resume qunit
ok(1,'entered qunit again');
ok(ed.getContent()== 'expected content') // < causes exception, no getContent() yet.
}
R.tinymce.onAddEditor.add(myfun)
in an inner iframe on the page will cause an exception (TypeError: ed.getContent is not a function),
but nothing in Qunit status area tells this. I see 0 failures.
(R being the inner iframe, using technique here: http://www.mattevanoff.com/2011/01/unit-testing-jquery-w-qunit/) Would I be correct in assuming this isn't the best way to go for testing sequences of UI interaction that cause certain results? Is it always better to use something like selenium, even for some mostly-javascript oriented frontend web-app tests?
As a side note, the Firefox console shows the console.log below the exception here, even though it happened first... why?
If you look into qUnit source code, there are two mechanisms handling exceptions. One is controlled by config.notrycatch setting and will wrap test setup, execution and teardown in try..catch blocks. This approach won't help much with exceptions thrown by asynchronous tests however, qUnit isn't the caller there. This is why there is an additional window.onerror handler controlled by Test.ignoreGlobalErrors setting. Both settings are false by default so that both kinds of exceptions are caught. In fact, the following code (essentially same as yours but without TinyMCE-specific parts) produces the expected results for me:
test("foo", function()
{
stop();
function myfun(ed)
{
start();
ok(1, 'entered qunit again');
throw "bar";
}
setTimeout(myfun, 1000);
});
I first see a passed tests with the message "entered qunit again" and then a failed one with the message: "uncaught exception: bar." As to why this doesn't work for you, I can see the following options:
Your qUnit copy is more than two years old, before qUnit issue 134 was fixed and a global exception handler added.
Your code is changing Test.ignoreGlobalErrors setting (unlikely).
There is an existing window.onerror handler that returns true and thus tells qUnit that the error has been handled. I checked whether TinyMCE adds one by default but it doesn't look like it does.
TinyMCE catches errors in event handlers when calling them. This is the logical thing to do when dealing with multiple callbacks, the usual approach is something like this:
for (var i = 0; i < callbacks.length; i++)
{
try
{
callbacks[i]();
}
catch (e)
{
console.error(e);
}
}
By redirecting all exceptions to console.error this makes sure that exceptions are still reported while all callbacks will be called even if one of them throws an exception. However, since the exception is handled jQuery can no longer catch it. Again, I checked whether TinyMCE implements this pattern - it doesn't look like it.
Update: Turns out there is a fifth option that I didn't think of: the exception is fired inside a frame and qUnit didn't set up its global error handler there (already because tracking frame creation is non-trivial, a new frame can be created any time). This should be easily fixed by adding the following code to the frame:
window.onerror = function()
{
if (parent.onerror)
{
// Forward the call to the parent frame
return parent.onerror.apply(parent, arguments);
}
else
return false;
}
Concerning your side-note: the console object doesn't guarantee you any specific order in which messages appear. In fact, the code console.log("foo");throw "bar"; also shows the exception first, followed by the log message. This indicates that log messages are queued and handled delayed, probably for performance reasons. But you would need to look into the implementation of the console object in Firefox to be certain - this is an implementation detail.
I am interested in monitoring javascript errors and logging the errors with the callstack.
I am not interested to wrap everything in try-catch blocks.
According to this article http://blog.errorception.com/2011/12/call-stacks-in-ie.html
it's possible inside window.onerror "recursively call .caller for each function in the stack to know the previous function in the stack"
I tried to get the callstack:
window.onerror = function(errorMsg, url, lineNumber)
{
var stk = [], clr = arguments.callee.caller;
while(clr)
{
stk.push("" + clr);
clr = clr.caller;
}
// Logging stk
send_callstack_to_log(stk);
}
but only one step is possible even if the callstack was much longer:
(function()
{
function inside() {it.will.be.exception;};
function middle() {inside()};
function outside() {middle()}
outside();
})();
One step isn't interesting because onerror arguments give me even more information about it.
Yes, I tried it with IE according the article I mentioned above.
Remark: I also tried to open an account on "ERRORCAEPTION" to gather error log. I tested it with IE and "ERRORCAEPTION" recognize that the errors are coming from IE, but I can't find any callstack information in the log I've got there.
Unfortunately this log will not always be available, it lacks line numbers, you can not really rely on it.
Try https://qbaka.com
Qbaka automatically overload bunch of JavaScript functions like addEventListener, setTimeout, XMLHtppRequest, etc so that errors happening in callbacks are automatically wrapped with try-catch and you will get stacktraces without any code modification.
You can try atatus which provides javascript contextual error tracking: https://www.atatus.com/
Take a look here:
https://github.com/eriwen/javascript-stacktrace
That's the one I use on Muscula, a service like trackjs.
I have wrote a program to monitor js error. maybe it will help.
I used three kind of methods to catch exceptions, such as window.onerror, rewrite console.error and window.onunhandledrejection. So I can get Uncaught error, unhandled promise rejection and Custom error
Take a look here: https://github.com/a597873885/webfunny_monitor
or here: https:www.webfunny.cn
It will be help
I didn't use throw new ReferenceError much before, and when I am using, I found out it will stop the script:
alert("a"); //Yes
throw new ReferenceError("Error."); //Yes
alert("b"); //Nope
http://jsfiddle.net/DerekL/uKEZ4/
I just want to throw an error in the console without stopping the whole script. I tried to do this:
alert("a"); //Yes
try{
throw new ReferenceError("Error."); //Yes
}catch(e){}
alert("b"); //Yes
http://jsfiddle.net/DerekL/uKEZ4/1/
This will work, but I don't think this is the best approach. What is the best way to display an error message without stopping the script?
PS:
console.warn("Error");
won't work on IE.
This behavior is by design. Exception handling in JavaScript works just like it does in many other languages: C#, Java, Ruby, etc.
When an exception is thrown it will unwind the stack and it will skip execution of code until it is caught with a catch (where it will "resume" execution). If there is no catch, then it just skips off the end of the code entirely (script element, source file, REPL, etc). finally is also an option in cases (to "resume" execution), but there is nothing like On Error Resume Next; that's just not JavaScript.
There is nothing to change this behavior.
(I recommend just shimming IE to support console.)
Error just a simply Object.whataever you throw, they always break the exec flow.
I have
function Student(){
var that=this;
that.SaveChanges=function(){
//.....
}
function init(){
that.SaveChanges1();
}
init();
}
<script type="text/javascript">
$(document).ready(function () {
var student=new Student();
});
</script>
With jquery-1.4.4.min.js, I could not save changes, because I made error, but rest of the application work.
With jquery-1.7.1.min.js I get error Object # has no method 'SaveChanges1' and rest of the application does not work.
OR
that.SaveChanges1 is not a function
[Break On This Error]
(77 out of range 4)
What should I do to work like with jquery-1.4.4.min.js?
I think you should try NOT to make errors in your javascript... It's good that it blows up, at least it warns you that something doesn't work! Perhaps you should try running some javascript or selenium tests and perhaps a jslint check to make sure that you don't break any of your javascript functionality!
If you want to ignore your errors in some parts of your program, you can do so by using exception handling. But, you cannot just blindly ignore all errors because when a portion of your script gets an error, that portion of the script has to stop executing as there is no orderly way to continue execution after an error. The javascript interpreter doesn't know which types of errors are harmless and which types mess up the whole script.
To catch an exception in one part of the script and continue executing other parts, you can add your own exception handling like this:
try {
// your code here that might cause a run-time error
} catch(e) {
// might want to put some debugging code here so you know that an error was thrown
}
// more code here that will execute even if the previous code threw an error
Note: you can use exception handling for run-time execution errors. You cannot use it for syntax errors that prevent compilation of the javascript code because when that happens, the interpreter can't even understand your code.