I'm writing a global error handling "module" for one of my applications.
One of the features I want to have is to be able to easily wrap a function with a try{} catch{} block, so that all calls to that function will automatically have the error handling code that'll call my global logging method. (To avoid polluting the code everywhere with try/catch blocks).
This is, however, slightly beyond my understanding of the low-level functioning of JavaScript, the .call and .apply methods, and the this keyword.
I wrote this code, based on Prototype's Function.wrap method:
Object.extend(Function.prototype, {
TryCatchWrap: function() {
var __method = this;
return function() {
try { __method.apply(this, arguments) } catch(ex) { ErrorHandler.Exception(ex); }
}
}
});
Which is used like this:
function DoSomething(a, b, c, d) {
document.write(a + b + c)
alert(1/e);
}
var fn2 = DoSomething.TryCatchWrap();
fn2(1, 2, 3, 4);
That code works perfectly. It prints out 6, and then calls my global error handler.
My question is: will this break something when the function I'm wrapping is within an object, and it uses the "this" operator? I'm slightly worried since I'm calling .apply, passing something there, I'm afraid this may break something.
Personally instead of polluting builtin objects I would go with a decorator technique:
var makeSafe = function(fn){
return function(){
try{
return fn.apply(this, arguments);
}catch(ex){
ErrorHandler.Exception(ex);
}
};
};
You can use it like that:
function fnOriginal(a){
console.log(1/a);
};
var fn2 = makeSafe(fnOriginal);
fn2(1);
fn2(0);
fn2("abracadabra!");
var obj = {
method1: function(x){ /* do something */ },
method2: function(x){ /* do something */ }
};
obj.safeMethod1 = makeSafe(obj.method1);
obj.method1(42); // the original method
obj.safeMethod1(42); // the "safe" method
// let's override a method completely
obj.method2 = makeSafe(obj.method2);
But if you do feel like modifying prototypes, you can write it like that:
Function.prototype.TryCatchWrap = function(){
var fn = this; // because we call it on the function itself
// let's copy the rest from makeSafe()
return function(){
try{
return fn.apply(this, arguments);
}catch(ex){
ErrorHandler.Exception(ex);
}
};
};
Obvious improvement will be to parameterize makeSafe() so you can specify what function to call in the catch block.
2017 answer: just use ES6. Given the following demo function:
function doThing(){
console.log(...arguments)
}
You can make your own wrapper function without needing external libraries:
function wrap(someFunction){
function wrappedFunction(){
var newArguments = [...arguments]
newArguments.push('SECRET EXTRA ARG ADDED BY WRAPPER!')
console.log(`You're about to run a function with these arguments: \n ${newArguments}`)
return someFunction(...newArguments)
}
return wrappedFunction
}
In use:
doThing('one', 'two', 'three')
Works as normal.
But using the new wrapped function:
const wrappedDoThing = wrap(doThing)
wrappedDoThing('one', 'two', 'three')
Returns:
one two three SECRET EXTRA ARG ADDED BY WRAPPER!
2016 answer: use the wrap module:
In the example below I'm wrapping process.exit(), but this works happily with any other function (including browser JS too).
var wrap = require('lodash.wrap');
var log = console.log.bind(console)
var RESTART_FLUSH_DELAY = 3 * 1000
process.exit = wrap(process.exit, function(originalFunction) {
log('Waiting', RESTART_FLUSH_DELAY, 'for buffers to flush before restarting')
setTimeout(originalFunction, RESTART_FLUSH_DELAY)
});
process.exit(1);
Object.extend(Function.prototype, {
Object.extend in the Google Chrome Console gives me 'undefined'
Well here's some working example:
Boolean.prototype.XOR =
// ^- Note that it's a captial 'B' and so
// you'll work on the Class and not the >b<oolean object
function( bool2 ) {
var bool1 = this.valueOf();
// 'this' refers to the actual object - and not to 'XOR'
return (bool1 == true && bool2 == false)
|| (bool1 == false && bool2 == true);
}
alert ( "true.XOR( false ) => " true.XOR( false ) );
so instead of
Object.extend(Function.prototype, {...})
Do it like:
Function.prototype.extend = {}
Function wrapping in good old fashion:
//Our function
function myFunction() {
//For example we do this:
document.getElementById('demo').innerHTML = Date();
return;
}
//Our wrapper - middleware
function wrapper(fn) {
try {
return function(){
console.info('We add something else', Date());
return fn();
}
}
catch (error) {
console.info('The error: ', error);
}
}
//We use wrapper - middleware
myFunction = wrapper(myFunction);
The same in ES6 style:
//Our function
let myFunction = () => {
//For example we do this:
document.getElementById('demo').innerHTML = Date();
return;
}
//Our wrapper - middleware
const wrapper = func => {
try {
return () => {
console.info('We add something else', Date());
return func();
}
}
catch (error) {
console.info('The error: ', error);
}
}
//We use wrapper - middleware
myFunction = wrapper(myFunction);
Here is an ES6 style:
const fnOriginal = (a, b, c, d) => {
console.log(a);
console.log(b);
console.log(c);
console.log(d);
return 'Return value from fnOriginal';
};
const wrapperFunction = fn => {
return function () {
try {
const returnValuFromOriginal = fn.apply(this, arguments);
console.log('Adding a new line from Wrapper :', returnValuFromOriginal);
} catch (ex) {
ErrorHandler.Exception(ex);
}
};
};
const fnWrapped = wrapperFunction(fnOriginal);
fnWrapped(1, 2, 3, 4);
The following wrapping utility takes a function and enables the developer to inject a code or wrap the original:
function wrap(originalFunction, { inject, wrapper } = {}) {
const wrapperFn = function(...args) {
if (typeof inject === 'function') {
inject(originalFunction, this);
}
if (typeof wrapper === 'function') {
return wrapper(originalFunction, this, args);
}
return originalFunction.apply(this, args);
};
// copy the original function's props onto the wrapper
for(const prop in originalFunction) {
if (originalFunction.hasOwnProperty(prop)) {
wrapperFn[prop] = originalFunction[prop];
}
}
return wrapperFn;
}
Usage example:
// create window.a()
(function() {
const txt = 'correctly'; // outer scope variable
window.a = function a(someText) { // our target
if (someText === "isn't") {
throw('omg');
}
return ['a', someText, window.a.c, txt].join(' ');
};
window.a.c = 'called'; // a.c property example
})();
const originalFunc = window.a;
console.log(originalFunc('is')); // logs "a is called correctly"
window.a = wrap(originalFunc);
console.log(a('is')); // logs "a is called correctly"
window.a = wrap(originalFunc, { inject(func, thisArg) { console.log('injected function'); }});
console.log(a('is')); // logs "injected function\na is called correctly"
window.a = wrap(originalFunc, { wrapper(func, thisArg, args) { console.log(`doing something else instead of ${func.name}(${args.join(', ')})`); }});
console.log(a('is')); // logs "doing something else instead of a(is)"
window.a = wrap(originalFunc, {
wrapper(func, thisArg, args) {
try {
return func.apply(thisArg, args);
} catch(err) {
console.error('got an exception');
}
}
});
a("isn't"); // error message: "got an exception"
The last example demonstrates how to wrap your function with a try-catch clause
As far as polluting the namespaces, I'm actually going to pollute them some more...
Since everything that happens in JS is initiated by an event of some kind, I'm planning to call my magical wrapper function from within the Prototype Event.observe() method, so I don't need to call it everywhere.
I do see the downsides of all this, of course, but this particular project is heavily tied to Prototype anyway, and I do want to have this error handler code be as global as possible, so it's not a big deal.
Thanks for your answer!
Related
If you create an object with functions that return this, you can create a chain of functions that were called previously and create a cascade of function calls:
var i = {
foo: function () {
// Something here...
return this;
},
bar: function () {
// Something here...
return this;
}
};
i.foo().bar().foo()
But what if an error occurs in bar and I don't want to call foo in that case? How do I break the cascade?
If it is at all possible, I would like to avoid try/catch statements.
Ok, so one straightforward thing is that if you want to handle the case without try/catch you have to put if condition in your functions and obviously you have to return something, so that you can execute further functions on that context instead of exception. So try creating all functionality in a object, and allow execution of your function logic only if someone extends. and on your failure return the base, otherwise return current object. In this was you can avoid creating objects every time.
Example:
Lets Consider You have BaseService where all functionalities are defined, and putting a Layer over it to just extend further, so you can go for this pattern:
foo: function() {
if(<function foo does not belongs to this>) {
.......
.......
if(<on logical failure>) {
return this.__proto__;
}
.......
.......
}
return this;
}
Here is a working snippet:
function BaseService() {
var dataBucket = [13, 50, 45, 57, 95];
this.foo = function() {
if (Object.values(this).indexOf(arguments.callee) === -1) {
console.log('processing foo');
}
return this;
}
this.bar = function() {
if (Object.values(this).indexOf(arguments.callee) === -1) {
console.log('processing bar');
}
return this;
}
this.processValIfExists = function(val) {
if (Object.values(this).indexOf(arguments.callee) === -1) {
console.log('processing processValIfExists');
if (dataBucket.indexOf(val) > -1) {
//process the value further
} else {
return this.__proto__;
}
}
return this;
}
};
//define the extended service, you can add further
//functionalities here. eg: createing the dataBucket here from args
function WrapperService() {};
WrapperService.prototype = new BaseService(); // just extend from any service and use
var svc = new WrapperService();
console.log('----------Executes All-----------');
svc.foo().bar().processValIfExists(95).foo().bar();
console.log('----------Executes upto processValIfExists-----------');
svc.foo().bar().processValIfExists(100).foo().bar();
Note that its just a different approach that came to my mind, and to check for the current invoking method I tried to make the code generic instead of checking if its instance of WrapperService in a BaseService function in order to avoid code coupling and can be extend from any other Service as well.
One could return a new empty instance of i, then on error return an empty obect:
class Chainable {
constructor(data){
this.data = data;
}
foo (foo) {
//if an error occured
if(foo == 10) return new Chainable();
// Something here...
return new Chainable(this.data + foo);
},
bar () {
//if were in an error, fail silently
if(!this.data) return this;
// Something here...
return this;
}
}
(new Chainable(1))
.foo(5).bar().bar().data // 6
(new Chainable(1))
.foo(10).bar().bar().data //undefined
Maybe not what you wanted, but Promises are great for chaining and for error handling:
var i = {
count: 0,
foo: function () {
// Something here...
this.count++;
console.log('foo');
return this.count < 4 ?
Promise.resolve(this) :
Promise.reject(new Error('Count too high!'));
},
bar: function () {
// Something here...
this.count++;
console.log('bar');
return this.count < 4 ?
Promise.resolve(this) :
Promise.reject(new Error('Count too high! Count is ' + this.count));
}
};
i.foo() // first
.then(i => i.bar()) // second
.then(i => i.foo()) // third
.then(i => i.bar()) // too much!
.then(i => i.whatIsThis()) // will not run
.then(i => i.whatIsThis()) // will not run
.catch(error => console.log(error.message));
I have several functions of the form:
this.something = function (which) {
// One or many.
if (!Array.isArray(which)) {
// Normal - just one.
doSomething(which);
} else {
// To all!
which.forEach(function (thing) {
// Note the recursion
something(thing);
});
}
};
Is there a tidier way to do this?
this.something = function(which) {
(Array.isArray(which) ? which : [which]).forEach(function(thing) {
doSomething(thing);
});
};
Not really a fan, but you often see this:
// A function that handles values as a single parameter, or inside an array
var doSomething(x) {
if (Array.isArray(x)) {
x.forEach(doSomething);
} else {
console.log(x);
}
}
Which you could extract from doSomething and apply in a utility method like so:
var ifArrayForEach = f => x => Array.isArray(x) ? x.forEach(f) : f(x);
var doSomething = x => console.log(x);
var doSomethingArrayOrNot = ifArrayForEach(doSomething);
doSomethingArrayOrNot("Hello world");
doSomethingArrayOrNot(["Hello", "world"]);
Again... I'm not a big fan, but sometimes it can be useful. I'd personally just check before calling. At some point you'll have to know what data you're handling anyway...
Not sure if this meets the "Tidier" request you're looking for, but you could always handle it in a try/catch.
try {
which.forEach(function (thing) {
something(thing);
});
} catch (e) {
if (e instanceof TypeError) {
doSomething(which);
}
}
I have a JavaScript object
myObject = function () {
var that = {};
...
that.myMethod1 = myMethod1;
that.myMethod2 = myMethod2;
...
that.myMethodN = myMethodN;
return that;
}
I want to add the exact same pre and post logic to every method. For example a log for entering the method and for exiting the method.
I could with a prePostLogic function such as
function prePostLogic(f2) {
console.log('>> enter');
f2();
console.log('<< exist');
}
and then do:
myObject = {
...
that.myMethod1 = prePostLogic(myMethod1);
that.myMethod2 = prePostLogic(myMethod2);
...
that.myMethodN = prePostLogic(myMethodN);
return that;
}
But what I'd really like is to not have to wrap every method but to write something that would iterate over all methods and wrap them for me. This is so when someone adds a new method they don't have to wrap it.
Please help me?
Thanks
something that would iterate over all methods and wrap them for me
Exactly, just do that:
for (var prop in that)
that[prop] = makePrePostLogic(that[prop]);
function makePrePostLogic(fn) {
return function withLogic() {
console.log(">> enter "+fn.name);
var res = fn.apply(this, arguments);
console.log("<< exit "+fn.name);
return res;
};
}
function prePostLogic(f2) {
return (function(){
console.log('>> enter');
f2();
console.log('<< exit');
});
}
var func = function(){
console.log("Hello World");
}
var method = prePostLogic(func);
method();
In your case
for (var prop in myObject){
if(typeof myObject[prop] == "function"){
myObject[prop] = prePostLogic(myObject[prop]);
}
}
I'm using a run-time assignment of functions to account for browser differences. However for un-supported browsers, I want to return an empty function so that a JavaScript error is not thrown.
But, jslint complains about empty functions. What is the jslint happy way to do this?
Empty block.
$R.functionNull = function () {
// events not supported;
};
$R.Constructor.prototype.createEvent = (function () {
if (doc.createEvent) {
return function (type) {
var event = doc.createEvent("HTMLEvents");
event.initEvent(type, true, false);
$NS.eachKey(this, function (val) {
val.dispatchEvent(event);
});
};
}
if (doc.createEventObject) {
return function (type) {
var event = doc.createEventObject();
event.eventType = type;
$NS.eachKey(this, function (val) {
val.fireEvent('on' + type, event);
});
};
}
return $R.functionNull;
}());
You can add a body to your function and have it return undefined:
$R.functionNull = function() {
// Events not supported.
return undefined;
};
This keeps the same semantics as a "truly empty" function, and should satisfy JSLint.
Use the lambda expression:
$R.functionNull = () => void 0;
For me this works best:
emptyFunction = Function();
console.log(emptyFunction); // logs 'ƒ anonymous() {}'
console.log(emptyFunction()); // logs 'undefined'
It's so short that I wouldn't even assign it to a variable (of course you can also use a constant-like variable "EF" or so, that's even shorter and doesn't need the additioal "()" brackets). Just use "Function()" anywhere you need a truly empty function, that doesn't even have a name, not even when you assign it to a variable, and that's the small behaviour difference between my solution and Frédéric's:
// --- Frédéric ---
emptyFunction = function() {
return undefined;
}
console.log(emptyFunction.name); // logs '"emptyFunction"'
// --- me ---
emptyFunction = Function();
console.log(emptyFunction.name); // logs '""' (or '"anonymous"' in chrome, to be fair)
What about returning
return () => undefined;
instead of
return $R.functionNull;
I was working on some code earlier today, when I realized, "Hey! This code would be more concise and semantic if I abstracted the idea of a boolean not out of an anonymous function and into a prototype function..."
Consider a predicate generator:
function equalTo(n) {
return function(x) {
return n==x;
};
}
So you can use it like so:
[1,2,3,4,1,2,3,4].filter(equalTo(2)) == [2,2]
Now, my idea is to make a predicate "inverser":
Function.prototype.not = function() {
//???
}
So that you can say:
[1,2,3,4,1,2,3,4].filter(equalTo(2).not) == [1,3,4,1,3,4]
My first stab at the implementation was probably very naive:
Function.prototype.not = function () {
return ! this(arguments);
}
And probably why it didn't work.
How would you implement this function, and why?
I'm just trying to wrap my head around functional ideas, and know JavaScript well enough to know it can be used to do this, but just not how.
Your implementation won't work for several reasons:
You need to return a function, not a boolean.
You should pass the arguments as-is, not wrapped in an array.
You should preserve the context (this keyword) that the function would have been called in.
I would implement it like this:
Function.prototype.not = function (context) {
var func = this;
return function() { return !func.apply(context || this, arguments); };
}
I return an anonymous function (function() { ... })
I call apply to call the original function in the current contexts with the actual arguments.
(EDIT) Free bonus: I added an optional context parameter which will override this for the callback.
I would probably do it like so (but perhaps with some sort of namespacing):
function not (x) {
return !x;
}
function id (x) {
return x;
}
function compose (/*funcs*/) {
var args = arguments.length
? Array.prototype.slice.call (arguments)
: [id]
;
return function () {
var val = args [args.length - 1].apply (null, arguments);
for (var i = args.length - 2; i >= 0; --i) {
val = args [i] (val);
}
return val;
};
}
[1,2,3,4,1,2,3,4].filter (compose (not, equalTo (2)));
Using your idea:
function equalTo(n) {
var fn = function(x) {
return n == x;
};
fn.not = function(x) {
return n != x; // use this for simpler conditions
return !fn.apply(this, arguments); // use this for more complex logic
}
return fn;
}
So your example would work:
[1,2,3,4,1,2,3,4].filter(equalTo(2).not) == [1,3,4,1,3,4]
Edit: You can write a helper function (better name to be found) so not doesn't need to be redefined every time:
function generateFnWithNot(fn) {
return function () {
var f = fn.apply(this, arguments);
f.not = function () {
return !f.apply(this, arguments);
}
return f;
};
}
So when you're defining your functions, you can define them as normal with the exception of wrapping a generateFnWithNot call:
var equalTo = generateFnWithNot(function (n) {
return function (x) {
return n == x;
};
});
equalTo(5) // resolves to function () { return n == 5; }
equalTo(5).not // resolves to function () { return n != 5; }