如何包装在Javascript功能?
-
11-07-2019 - |
题
我在写一个全球性的错误处理“模块”为我的应用程序之一。
一个我想拥有的功能是能够很容易地包裹的功能与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,然后调用我的全局错误处理程序。
我的问题是:将这个碰坏了,当我包装的功能是一个对象中,并使用了“这个”运营商?我略有担心,因为我打电话。适用,路过的东西在那里,恐怕这可能碰坏。
解决方案
个人而不是污染内置对象我会去与一个装饰技术:
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);
Object.extend(Function.prototype的,{ Object.extend 谷歌浏览器控制台给我“未定义” 那么这里的一些工作的例子:
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 ) );
所以不是 Object.extend(Function.prototype的,{...}) 不喜欢它: Function.prototype.extend = {}
<强> 在良好的旧方式功能包裹: 强>
//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);
<强> 同样在ES6样式: 强>
//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);
至于污染命名空间,我究竟要污染他们更多一些...... 由于这种情况发生在JS一切都是由某种类型的事件开始,我打算从原型Event.observe()方法中调用我的神奇包装函数,所以我不需要到处调用它。
我看到这一切的缺点,当然,但这个特殊项目的严重依赖反正原型,我也想有这样的错误处理代码是全球越好,所以它不是一个大问题。
谢谢您的回答!