una - tablas en javascript ejemplos
¿Cómo envuelvo una función en Javascript? (4)
Estoy escribiendo un "módulo" de manejo de errores global para una de mis aplicaciones.
Una de las características que quiero tener es poder ajustar fácilmente una función con un bloque Try {} Catch {}, para que todas las llamadas a esa función tengan automáticamente el código de manejo de errores que llamará a mi método de registro global. (Para evitar contaminar el código en todas partes con bloques try / catch).
Sin embargo, esto está un poco más allá de mi comprensión del funcionamiento de bajo nivel de Javascript, los métodos .call y .apply, y la palabra clave "this".
Escribí este código, basado en el método Function.wrap de Prototype:
Object.extend(Function.prototype, {
TryCatchWrap: function() {
var __method = this;
return function() {
try { __method.apply(this, arguments) } catch(ex) { ErrorHandler.Exception(ex); }
}
}
});
Que se usa así:
function DoSomething(a, b, c, d) {
document.write(a + b + c)
alert(1/e);
}
var fn2 = DoSomething.TryCatchWrap();
fn2(1, 2, 3, 4);
Ese código funciona perfectamente. Imprime 6 y luego llama a mi controlador de error global.
Mi pregunta es ... ¿Esto romperá algo cuando la función que estoy envolviendo está dentro de un objeto, y usa el operador "this"? Estoy un poco preocupado ya que estoy llamando. Aplicar, pasar algo allí, me temo que esto puede romper algo.
En cuanto a la contaminación de los espacios de nombres, voy a contaminarlos un poco más ... Dado que todo lo que sucede en JS es iniciado por un evento de algún tipo, planeo llamar a mi función envoltura mágica desde el evento prototipo. Método .observe (), así que no necesito llamarlo a todos lados.
Veo las desventajas de todo esto, por supuesto, pero este proyecto en particular está estrechamente relacionado con Prototype de todos modos, y quiero que este código de controlador de errores sea lo más global posible, por lo que no es gran cosa.
¡Gracias por tu respuesta!
Personalmente, en vez de contaminar los objetos incorporados, iría con una técnica de decorador:
var makeSafe = function(fn){
return function(){
try{
return fn.apply(this, arguments);
}catch(ex){
ErrorHandler.Exception(ex);
}
};
};
Puedes usarlo así:
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);
Pero si tiene ganas de modificar prototipos, puede escribirlo así:
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);
}
};
};
La mejora evidente será parametrizar makeSafe () para que pueda especificar a qué función llamar en el bloque catch.
Object.extend (Function.prototype, { Object.extend en la consola de Google Chrome me da ''undefined'' Bien, aquí hay un ejemplo de trabajo:
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 ) );
así que en lugar de Object.extend (Function.prototype, {...}) Hazlo como: Function.prototype.extend = {}
Respuesta de 2017 : solo use ES6. Dada la siguiente función de demostración:
var doThing = function(){
console.log(...arguments)
}
Puede crear su propia función de contenedor sin necesidad de bibliotecas externas:
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
}
En uso:
doThing = wrap(doThing)
doThing(''one'', {two:''two''}, 3)
Respuesta 2016 : use el módulo wrap
:
En el siguiente ejemplo, estoy envolviendo process.exit()
, pero esto funciona felizmente con cualquier otra función (incluido el navegador JS también).
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);