I am developing my first Javascript app and I am trying to go object oriented.
There is a basic closure that returns my primary object and every function I invoke rests in that object. Some pseudo code would look like this:
primary = (function(){
var object = {
doSomething = function(){};
},
return {intance:function(return object)}
});
//invocation
primary.instance().doSomething();
What I am trying to achieve is to attach an error handler function to my object, so that whenever there is an internal error, it is cought, and I don't have to wrap every function call in a try catch block.
I tried object.onerrorbut the error went on to window object. Maybe I am getting the concept wrong. I tried searching on Github for some simpler framework that includes structured error handling, but no luck. I am pretty familiar with this in PHP, but I haven't done this so far in Javascript. Can somebody show me an example how it is done right?
EDIT: I know that structured error handling goes further, I am just trying to get a root handler, so that no errors / exceptions can pass on to the window object
Dealing with the error event without a try catch block will halt the execution of your script (except for any asynchronous functions that have already been called).
You can suppress (non-ajax, non-syntax) errors by capturing them on document.body or a more specific object, and stop them being thrown to the user (or reaching the window object) by using e.preventDefault() or return false, and send them to a global/object handler (to inspect or log) by passing the event object as an argument - but any of those options will stop your script execution beyond the point of error. That's the main benefit of a try catch block, and as far as I know there is no way around that.
Related
I'm having a strange issue that's being thrown in Firefox when using my Dojo (v.1.10.0) application.
Here is the following error that I'm seeing in Firefox:
Exception
{ message: "",
result: 2147549183,
name: "NS_ERROR_UNEXPECTED",
filename: "http://localhost:8888/dojo/on.js",
lineNumber: 354,
columnNumber: 0,
inner: null,
data: null
}
""
Unfortunately, I'm not sure where to go with this in my application. Can anyone point me in the right direction?
On line 354 of dojo/on, this is happening:
if(has("dom-addeventlistener")){
// emitter that works with native event handling
on.emit = function(target, type, event){
if(target.dispatchEvent && document.createEvent){
// use the native event emitting mechanism if it is available on the target object
// create a generic event
// we could create branch into the different types of event constructors, but
// that would be a lot of extra code, with little benefit that I can see, seems
// best to use the generic constructor and copy properties over, making it
// easy to have events look like the ones created with specific initializers
var ownerDocument = target.ownerDocument || document;
var nativeEvent = ownerDocument.createEvent("HTMLEvents");
nativeEvent.initEvent(type, !!event.bubbles, !!event.cancelable);
// and copy all our properties over
for(var i in event){
if(!(i in nativeEvent)){
nativeEvent[i] = event[i];
}
}
return target.dispatchEvent(nativeEvent) && nativeEvent; // Line 354
}
return syntheticDispatch.apply(on, arguments); // emit for a non-node
};
}
This is a generic FF error message... it's usually triggered by a timing or race condition, which may explain why it's showing up via dojo/on. Maybe the target or event handler that you're trying to work with is acting on something that has been removed, etc. It's unclear without knowing what event is triggering it or without seeing your full code example.
For example, maybe you're trying to add event listeners before the DOM is available, but that's just a guess. Or maybe the target node doesn't exist.
You can use the debugger to see the values of the event parameters, or you can look at your various event registration mechanisms, etc.
We have a similar issue using intern 2.0 and unit tests creating native select boxes.
Some library code (verified that its not our own) triggers a dojo.emit() which causes the internal error.
We're trying to identify the problem in more detail. If you find something please let us know as well!
we were also getting same exception at exactly same point,
for us, we replaced our code elementReference.destroy() // destroy is a dojo function with elementReference.domNode.remove() and it solved our problem.
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 have a Javascript function that's fired on the onclick event of a button on my webform. It's possible for invalid parameters to be passed to the function, in which case I'd like to throw an error so that the browser can report to the user that something went wrong, and that they might want to check their configuration settings. However, throwing an error causes a postback as the return false; statement is never reached.
In this situation, what sort of feedback can/should I give to the user? I don't particularly want to throw up an alert as I'd prefer something more subtle. Any/all suggestions appreciated.
Try Catch Finally in JavaScript
Using exception handling you can throw the error as well as return the control as false based on your certain conditions
1)
For handling runtime errors:
use try/catch/finally
Reference: MDN try...catch
2)
For the feedback:
Instead of using the alert you can use a Dialog animation with fade in and after two seconds fade out effect.
For example look to this demo:
http://sandbox.scriptiny.com/javascript-fading/
I'm using jQuery 1.3.2 and it's breaking under Safari 4 for mysterious reasons.
All of my javascript references are made right before the tag, yet with the following code:
var status = $('#status');
status.change( function(){ /* ... */ } );
The following error is displayed in the Web Inspector:
TypeError: Result of expression 'status.change' [undefined] is not a function.
However the error is not encountered if I eliminate the variable assignment attach the change method directly like so:
$('#status').change( function(){ /* ... */ } );
Why? I need to use variables for this and several other findById references because they're used many times in the script and crawling the DOM for each element every time is regarded as bad practice. It shouldn't be failing to find the element, as the javascript is loaded after everything except and .
Try changing the variable to something other than "status."
It's confusing your variable with window.status (the status bar text). When I typed var status = $('#status') into the debugging console, the statusbar changed to [Object object]. Must be a bug in Safari.
If you put the code inside a function, so that status becomes a function-local variable, it should work.
It's standard practice in jQuery to wrap things in a
$.onready(function() {
});
This makes sure the DOM is loaded before you try to manipulate it.