原文地址:
作者:
|
Kris Zyp
|
项目所有者:
|
Kris Zyp
|
起自:
|
1.7.0
|
dojo/aspect 模块可以提供 aop(面向切面)编程能力,即可以给现存的方法扩展功能。dojo/aspect 模块返回三个函数。注意:如果你需要的仅仅是关联 DOM Events ,而非常规的的 JS 对象和方法,那么建议你用 dojo/on ,比用 dojo/aspect 强。
after()
模块包含一个 after 函数用来给一个方法添加 after advice。这个 advising function 会在主方法调用完后被触发调用。after 函数签名如下:
-
after(target, methodName, advisingFunction, receiveArguments);
target 参数是拥有某个方法的 object。methodName 参数是需要追加 advice 的原始函数。advisingFunction 参数是原始函数被调用后需要被触发的函数。原始函数的返回值将作为第一个参数传递给 advising function。advising function 必须返回一个值用于替换原始函数的返回值。
示例:
-
define(["dojo/aspect"], function(aspect){
-
aspect.after(dojo, "xhr", function(deferred){
-
// this is called after any dojo.xhr call
-
});
// this will execute the original dojo.xhr method and then our advising function
-
dojo.xhr("GET", {...});
-
});
我们也可以使用 dojo.require(“dojo.aspect”) 来加载 dojo/aspect,这样它就可以通过 dojo.aspect 全局访问了。
-
dojo.require("dojo.aspect");
-
dojo.aspect.after(dojo, "xhr", function(response){
-
...
-
});
advising function 必须返回一个值用于替换原始函数的返回值。示例:
译注:这里的 deferred 参数就是原始函数的返回结果。
-
aspect.after(dojo, "xhr", function(deferred){
-
// returning a value replaces the return value
-
return deferred.then(function(response){
-
return dojo.fromJson(response);
-
});
-
});
-
var parsedResponse = dojo.xhr("GET", {...});
通过将 receiveArguments 设置为 true,我们就可以让 advisory function 能够访问原始方法的原始参数。示例:
-
aspect.after(dojo, "xhr", function(method, args){
-
// now we have access to the original arguments
-
}, true);
before()
模块包含一个 before 函数用来给一个方法添加 before advice。这个 advising function 会在主方法调用之前被触发调用。before 函数签名如下:
-
before(target, methodName, advisingFunction);
target 参数是拥有某个方法的 object。methodName 参数是需要追加 advice 的原始函数。advisingFunction 参数是原始函数被调用之前需要被触发的函数。传递给原始函数的参数会被传递给 advising function。advising function 执行完毕后会返回一个数组,用于替换原始函数的参数(或者是下一个 before advice。译注:也就是说 before 可以层层包裹)。示例:
-
define(["dojo/aspect"], function(aspect){
-
aspect.before(dojo, "xhr", function(method, args){
-
// this is called before any dojo.xhr call
-
if(method == "PUT"){
-
// if the method is PUT, change it to a POST and put the method in the parameter string
-
args.url += "?x-method=PUT";
-
// return the new args
-
return ["POST", args];
-
}
-
});
-
// this will execute the original our advising function and then dojo.xhr
-
dojo.xhr("PUT", {...});
-
});
around()
模块最后包含一个 around(环绕) 函数用来给一个方法添加 around advice。
The provided advising function will be called in place of the main method, and the advising function will be passed a chaining function that can be used to continue to call execution to the next advice or original method.
译注:以上不大好翻译。保留原文,意译并加以发挥。around 会将原始函数包裹住,取代原始函数的调用,同时这种取代不打破原有函数的链式调用。所谓链式调用类似于unix 的管道,前一个函数的输出作为后一个函数的输入 ,从而形成一个长长的执行链,而我们可能想对某一个节点偷梁换柱,而不影响前后函数的执行,这就是 around 的用处。而before,after 也会往这个链条上加入一些执行节点。链式调用用 clojure 来描述更为清晰 (-> args func1 func2 func3 func4) 。
around 函数签名如下:
-
around(target, methodName, advisingFactory);
target 参数是拥有某个方法的 object。methodName 参数是需要追加 advice 的原始函数。The advisingFactory is a function that will be called immediately with a single argument that is a function that can be called to continue the execution. The advisingFactory should return a function that will be called when the method is called. The arguments used to call the method will be provided as the arguments to the returned advising function. The advising function’s return value will be returned from the method call. For example:
译注: 同样保留原文,意译并加以发挥。为了实现前面说的的效果,要取代原始函数而且不破坏调用链的执行,那么 aspect.around 的返回结果必定是个函数(所以下面例子中有 return function(method,args){..}),其函数签名必须同原始函数完全一致,同时在这个新函数内部对原始函数进行调用(即 var deferred = originalXhr(method,args) ),并将结果原封不动地返回(return deferred)。
从而我们可以知道了,作为 aspect.around 的第三个参数 advisingFactory 就是一个工厂函数,它接收的唯一一个参数即原始函数,将其包裹后生成一个替身。
-
define(["dojo/aspect"], function(aspect){
-
aspect.around(dojo, "xhr", function(originalXhr){
-
return function(method, args){
-
// doing something before the original call
-
var deferred = originalXhr(method, args);
-
// doing something after the original call
-
return deferred;
-
}
-
});
-
dojo.xhr("PUT", {...});
-
});
我们再看第二个例子,来自 API 文档:
-
around(obj, "foo", function(originalFoo){
-
return function(){
-
var start = new Date().getTime();
-
var results = originalFoo.apply(this, arguments); // call the original
-
var end = new Date().getTime();
-
console.log("foo execution took " + (end - start) + " ms");
-
return results;
-
};
-
});
阅读(1211) | 评论(0) | 转发(0) |