我正在为我的一个应用程序编写一个全局错误处理"模块".
我想要的一个功能是能够使用Try {} Catch {}块轻松包装函数,以便对该函数的所有调用将自动具有将调用我的全局日志记录方法的错误处理代码.(避免使用try/catch块在任何地方污染代码).
然而,这稍微超出了我对Javascript,.call和.apply方法以及"this"关键字的低级功能的理解.
我根据Prototype的Function.wrap方法编写了这段代码:
Object.extend(Function.prototype, { TryCatchWrap: function() { var __method = this; return function() { try { __method.apply(this, arguments) } catch(ex) { ErrorHandler.Exception(ex); } } } });
使用方式如下:
function DoSomething(a, b, c, d) { document.write(a + b + c) alert(1/e); } var fn2 = DoSomething.TryCatchWrap(); fn2(1, 2, 3, 4);
该代码完美无缺.它打印出6,然后调用我的全局错误处理程序.
我的问题是......当我正在包装的函数在一个对象中时它是否会破坏某些东西,它会使用"this"运算符?我有点担心,因为我打电话.在那里传递一些东西,我担心这可能会破坏一些东西.
我个人而不是污染内置对象,我会使用装饰技术:
var makeSafe = function(fn){ return function(){ try{ return fn.apply(this, arguments); }catch(ex){ ErrorHandler.Exception(ex); } }; };
你可以像这样使用它:
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);
但如果您确实想要修改原型,可以这样写:
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); } }; };
显而易见的改进是参数化makeSafe(),以便您可以指定在catch块中调用哪个函数.
2017答案:只需使用ES6.给出以下演示功能:
var doThing = function(){ console.log(...arguments) }
您可以创建自己的包装函数而无需外部库:
var wrap = function(someFunction){ var wrappedFunction = function(){ var args = [...arguments].splice(0) console.log(`You're about to run a function with these arguments: \n ${args}`) return someFunction(args) } return wrappedFunction }
正在使用:
doThing = wrap(doThing) doThing('one', {two:'two'}, 3)
2016答案:使用wrap
模块:
在下面的示例中,我正在包装process.exit()
,但这与任何其他功能(包括浏览器JS)也很愉快.
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);