使用AOP调用方法之前和之后的Javascript控制台输出

时间:2014-11-06 10:54:51

标签: javascript aop sapui5 function-composition modifier

我想测量方法的计算时间。

一个不错的方法是(How do you performance test JavaScript code?console.time('Function #1');console.timeEnd('Function #1');

我的想法是在生命周期方法上添加这些控制台输出。在这种情况下,使用SAPUI5,如createContent:funtion(){};方法。

这可以通过AOP使用before()after()来计算时间。

您会建议哪个AOP框架以及如何实现它,需要自动修改标识字符串"功能#1"

2 个答案:

答案 0 :(得分:1)

实际上不需要Javascript中的方面,因为您可以随时更改任何对象的任何功能。 JavaScript原型允许您在运行时操作对象的所有实例的方法实现。以下是您计划的两种方法。

您可以使用通用包装函数:

var measureId = 0;
var fnMeasureFunction = function(fnToMeasure) {
  console.time('measure'+ measureId);
  fnToMeasure();
  console.timeEnd('measure'+ measureId);
  measureId++;
}

无可否认,这需要您更改实际代码......

对于属于原型的静态函数或函数,您也可以做某事。来自外部的这种情况,无需对现有代码进行任何更改:

// any static function
var measureId = 0;
var fnOriginalFunction = sap.ui.core.mvc.JSViewRenderer.render;
sap.ui.core.mvc.JSViewRenderer.render = function() {
  console.time('measure'+ measureId);
  fnOriginalFunction.apply(this, arguments);
  console.timeEnd('measure'+ measureId);
  measureId++;
}

// any prototype function
var fnOriginalFunction = sap.m.Button.prototype.ontouchstart;
sap.m.Button.prototype.ontouchstart= function() {
  console.time('measure'+ measureId);
  fnOriginalFunction.apply(this, arguments);
  console.timeEnd('measure'+ measureId);
  measureId++;
}

答案 1 :(得分:0)

  

这可以通过AOP使用before()和after()来计算时间。

正如已经提到的,一个人真的不需要真正的面向方面的编程 为了在JavaScript中解决这样的任务。但是这种语言可能值得更加标准化 method-modifiers 以及现有的bind方法。

请回顾我最近关于此事的2篇帖子:

  

...以及如何在需要修改标识字符串的情况下实现它"功能#1"自动?

一个人不需要,因为控制台的time / timeEnd功能只需要 用于测量时间的相同入口和出口点(如秒表的启动/停止触发器)。 因此,与当前正在运行/测量的函数/方法的参考完全相符。

为了解决给定的任务,我建议around而不是beforeafter 前者的(function (Function) { var isFunction = function (type) { return ( (typeof type == "function") && (typeof type.call == "function") && (typeof type.apply == "function") ); }, getSanitizedTarget = function (target) { return ((target != null) && target) || null; } ; Function.prototype.around = function (handler, target) { // [around] target = getSanitizedTarget(target); var proceed = this; return (isFunction(handler) && isFunction(proceed) && function () { return handler.call(target, proceed, handler, arguments); }) || proceed; }; }(Function)); 产生的开销较小。下一个代码块示例性地显示了一个 可能的原型实施。它也是后续示例的基础 这最终可能会解决OP的任务。

target

下一个示例考虑到方法修改基本上依赖于 绑定到对象的功能。它不仅仅是功能包装。为了 为了不松动方法正在运行的上下文 context 必须被委派/ 在所有操作中都以calculate传递。

为此,该示例不会修改trigger,因为它未绑定到对象 但它改为var testObject = { calculate: function (hugeInteger) { var i = hugeInteger, k = 0 ; while (i--) { k++; } return k; }, trigger: function (hugeInteger) { this.result = this.calculate(hugeInteger); }, result: -1 }; console.log("testObject.result : ", testObject.result); console.log("testObject.trigger(Math.pow(2, 26)) : ", testObject.trigger(Math.pow(2, 26))); // takes some time. console.log("testObject.result : ", testObject.result); console.log("testObject.someTrigger(0) : ", testObject.trigger(0)); // logs immediately after. console.log("testObject.result : ", testObject.result); testObject.trigger = testObject.trigger.around(function (proceed, interceptor, args) { // before: console.time(proceed); // proceed: proceed.apply(this, args); // after: console.timeEnd(proceed); }, testObject); // omitting the 2nd argument - the [target] object - might break code that did work before. console.log("testObject.trigger(Math.pow(2, 26)) : ", testObject.trigger(Math.pow(2, 26))); console.log("testObject.result : ", testObject.result);

{{1}}