Sorry, development was temporarily suspended
Let's dress up your code with Jackets
- Conception
1.1 Pros & cons - Jacket
2.1. Constructor
2.2. Options - Usage examples
3.1. Functions
3.2. Singletons
3.3. Coffescript classes
3.4. Backbone extensions - Error handling
4.1. Out of the box
4.2. Configuring
4.3. Writing own handler - Additional features
5.1. Callbacks
5.2. Methods' protection
Ask yourself:
"How much i need of getting stack trace when an error occurs on client side?".
I want it badly, especially in production.
If you think too, I suppose that jacket - is what you need.
Suppose you have a function, that throws an exception:
var j = function () {
return _undefined;
}
using CoffeeScript:
j = ->
_undefined
You can handle stack trace only by "try & catch" construction, because window.onerror handler does not provide that. To get stack trace you might handle error by this way:
var handler = function(err) { /* handle, notify your server about this error */ }
var fn = function () {
try {
return _undefined;
} catch (e) {
handler(e);
}
}
However, in this case you have a one function call, that supposed to be handled. In case you need to handle and notify your server about all exceptions, raised by you client side application, you must have an easy way of code' wrapping.
- And what you might to do in this case?
- How to rid yourself from this boring work?
- How to speed up searching of code mistakes?
- Is there any way of easy code' wrapping?
Actual questions, aren't they? Let's look how Jacket can help us to answer them...
var j = Jacket(function () { /* use J instead of Jacket for convenience */
return _undefined;
});
Run
j();
/* console:
Anonymous266.constructor : _undefined is not defined
- at http://localhost:8008/examples/example255.js:2:10
- at http://localhost:8008/examples/example256.js:1:57
*/
Jacket.js is able to wrap classes, functions and objects. After exception handling, it will be thrown on and the script execution will be stopped by default.
pros | cons |
---|---|
|
|
In most situations you'll use Jacket.constructor function without new keyword. Using it with new keyword will instantiate wrapped function.
First case - wrap function, then instantiate it.
var fn = function(){};
fn = Jacket( fn );
new fn();
Second case - wrap and instantiate it instantly.
new Jacket( function(a){console.log(a)} )( 'hi!' );
/* console:
hi!
*/
Jacket( name, target, extention, methods, callback )
Argument | Type | Required | Description |
---|---|---|---|
name | String | false | name of the new class, that should be created |
target | Object Function |
true | object, what should be wrapped |
extention | Object | false | object, witch properties will extend target |
methods | Array RegExp |
false | array of method names, witch would be wrapped, or RegExp pattern |
callback | Function | false | post-hook, that should be applyed after method call, before returning of its results |
All Jacket options are storing in the Jacket.config object.
Name | Type | Default | Description |
---|---|---|---|
log_errors | Boolean | true | name of the new class, that should be created |
log_stacktrace | Boolean | true | |
log_callstack | Boolean | false | |
use_debugger | Boolean | false | |
throw_errors | Boolean | true | |
notify_url | String Boolean |
false | |
events_count | Integer | 100 |
Jacket has setup method, that helps to set option values.
console.log( Jacket.config );
/* console:
{"log_errors":true,"log_stacktrace":true,"log_callstack":false,"use_debugger":false,"throw_errors":false,"notify_url":false,"events_count":100}
*/
Let's begin with anonymous functions
var anonymous = function(msg) {
if (!arguments.length) arguments = _undefined;
console.log(msg);
}
var j = J(anonymous);
console.log(
j.wrapped,
j !== anonymous,
j()
);
/* console:
Anonymous269.constructor : _undefined is not defined
- at anonymous (http://localhost:8008/examples/example260.js:2:38)
- at http://localhost:8008/examples/example260.js:9:3
true true undefined
*/
Named functions are considered as classes and have protected name property, that Jacket uses to extend exception message explanation.
function sum(a, b) {
if (typeof a + typeof b !== 'numbernumber') {
throw new Error('Invalid arguments');
}
this.result = a + b;
return this.result;
}
console.log(
' - sum constructor: ', J(sum)(1, 1),
'\n - sum instance:', new J(sum)(1, 1)
)
J(sum)('oops!'); // will throw an error
console.log('continue...'); // will not be executed
// if J.config.throw_errors is positive
/* console:
- sum constructor: 2
- sum instance: {"result":2}
sum.constructor : Invalid arguments
- at sum (http://localhost:8008/examples/example261.js:3:11)
- at http://localhost:8008/examples/example261.js:14:7
continue...
*/
Imagine that one of your class must be instantiated once, and you want to know if it happens. Then you can pass Error object to Jacket, and it will do the rest of work.
var SingletonConstructor;
(function() {
var instance;
var crash = new Error('SingletonConstructor was called more than one time');
SingletonConstructor = function() {
if (typeof instance !== 'undefined') {
J.handle(crash); // throw an error if instance has been already created
++instance.callcount;
return instance;
}
this.callcount = 1;
return instance = this;
};
})();
new J(SingletonConstructor)(); // will create an instance
console.log( 'instance:', new J(SingletonConstructor)() );
/* console:
SingletonConstructor was called more than one time
- at http://localhost:8008/examples/example262.js:6:15
- at http://localhost:8008/examples/example262.js:21:3
instance: {"callcount":2}
*/
Classes represent a more complex structure than functions. They usually have suite of prototype's methods, instance methods and sometimes static methods. All methods of class are supposed to be wrapped. Instance methods, which were created in constructor supposed to be wrapped after constructor's code execution. If there are callings of these methods inside the constructor and one of them contains mistakes, exception should be catched inside constructor.
var _Class = (function _Class() {
function _Class(wishes) {
this.defInConst = function() {
return _undefined;
}
if (wishes)
this.defInConst();
}
return _Class;
}).call(window);
new J(_Class)().defInConst();
console.log('\n - compare theese outputs - \n');
new J(_Class)('call defInConst inside constructor');
/* console:
_Class.defInConst : _undefined is not defined
- at _Class.defInConst (http://localhost:8008/examples/example263.js:4:14)
- at http://localhost:8008/examples/example263.js:12:17
- compare theese outputs -
_Class.constructor : _undefined is not defined
- at _Class.defInConst (http://localhost:8008/examples/example263.js:4:14)
- at _Class (http://localhost:8008/examples/example263.js:7:12)
- at http://localhost:8008/examples/example263.js:16:14
*/
What functionality does it provide in case of error handling?
- It launches browser' debugger if Jacket.config.use_debugger is positive
- It outputs error message, stacktrace and callstack to console *
- It pushes these data to specified url if Jacket.config.notify_url is valid url string
- It calls your own handler, passing all needed information about an error
- It can prevent script execution stopping * depends on Jacket.config.log_errors, Jacket.config.log_stacktrace and Jacket.config.log_callstack respectively
/* create additional handler */
Jacket.handler = function(error_object, extended_error_msg_string, stacktace_array, callstack_array) {
/* your code */
}
- Handling exceptions, raised in function or in public methods of function instance (class)
- Notify your server about exceptions
- Calling a specific callback on each wrapped function call
You can specify a global callback function, that should be runned before each return statement of class' methods. This callback gets execution scope, class name, method name, method arguments and its result as arguments
|example265|