上篇介绍了PromiseEvent,本篇介绍Trigger - 基于Promise的aop的体现;(感觉自己的对这些命名一直都很挫,也懒得想了,所以就凑合的用)
Trigger
在目标对象上加入触发器功能,目标对象的方法就会具有方法注入功能,注入的方式有before(前置执行),after(后置执行)和round(环绕),另外还有一个exception模式,因为异常处理的模块还没完成,暂时先空缺。
接口方法
st.attachTrigger(target, mode, fnInterface); //后置注入方法 target.on(name, trName, fn, priority, eventMode) //前置置注入方法 target.onBefore(name, trName, fn, priority, eventMode) //方法环绕 target.onRound(name, trName, fn) //删除注入方法 target.off(name, trName) //删除前置注入方法 target.offBefore(name, trName) //替换目标对象的原始方法 target.extend(prop)
参数讲解
target : 目标对象;
mode:回调模式,同promisEvent的mode设置
iFace :自定义接口方法;在使用attachTrigger方法后,会在target上附加一些控制方法,为了避免重名和控制对外的方法,使用iFace来自定义
使用了attachTrigger后,会在target上附加上注入控制的方法,on,onBefore等
name :需要注入的target的方法名
trName : 加入触发回调名称
fn:注入方法,方法参数同PrmiseEvent的回调参数
priority :权重设置,同PrmiseEvent ;
eventMode :加入的事件模式,同PrmiseEvent
需要注意的是on和onBefore注入的方法接口是fn(e,arg,...)
e同PromiseEvent参数设置,唯一不同的是有两个新加入的控制:
e.preventDefault 阻止默认的方法,即target的原始方法; 但不会影响回调事件的
e.stop() 停止方法执行,无论是原始方法还是回调;
而onRound的是fn(originalFn,arg,..),环绕和前后置不冲突
originalFn : 需要环绕的方法;
使用样例
前后置
var result = []; var obj = { test: function(name) { result.push(name); } }; //加入触发器 st.attachTrigger(obj); //加入前置方法 obj.onBefore("test", "addBefore", function(d, name) { result.push('before-' + name) }); //加入后置方法 obj.on("test", "addAfter", function(d, name) { result.push('after-' + name) }); //执行,结果"before-bind,bind,after-bind" obj.test('bind');
自定义接口iFace
var obj1 = st.attachTrigger({ test: function(name) { result.push(name); } }, { //屏蔽后置方法on on: null, //将前置方法onBefore设置为bind onBefore: "bind" }) obj1.bind("test", "addBefore", function(d, name) { result.push('before-' + name); });
方法环绕
var obj3 = st.attachTrigger({ test: function(name) { result.push(name); } }); obj3.onRound("test", "roundTest", function(fn, name) { result.push('before'); fn(name); result.push('after'); }); obj3.test('round'); expect(result.join(',')).toBe("before,round,after");
promise控制
在前置和后置中都是通过promiseEvent的事件参数做promise控制,但在原始方法中,为了避免干预原始方法带来的混乱,则没有加入事件参数,而是通过使用JQuery的deffered来做控制
var obj = st.attachTrigger({ test: function(name) { //原始方法中使用jquery的deferred var d = $.Deferred(); setTimeout(function() { result.push(name); d.resolve(); }, 100); return d.promise(); } }); obj.onBefore('test', 'testBefore', function(d, name) { setTimeout(function() { result.push(name + '-before'); d.resolve(); }, 100); return d.promise(); }) obj.on('test', 'testAfter', function(d, name) { setTimeout(function() { result.push(name + '-after'); d.resolve(); }, 100); return d.promise(); }) $.when(obj.test('call')).done(function() { expect(result.join(',')).toBe('call-before,call,call-after'); })
结果传递
var obj = st.attachTrigger({ //promise参数传递 test: function(name) { var d = $.Deferred(); setTimeout(function() { d.resolve(name + '-base'); }, 100); return d.promise(); }, //return 结果传递 testReturn: function(name) { return name + "-base" } }); obj.on('test', 'testAfter', function(d, name) { setTimeout(function() { d.resolve(d.result + '-after'); }, 100); return d.promise(); }) obj.on('testReturn', 'testAfter', function(d, name) { setTimeout(function() { d.resolve(d.result + '-after'); }, 100); return d.promise(); }) $.when(obj.test('call')).done(function(data) { expect(data).toBe('call-base-after'); }); $.when(obj.testReturn('call2')).done(function(data) { expect(data).toBe('call2-base-after'); });
stop控制
var obj = st.attachTrigger({ test: function(name) { result.push(name); } }); obj.onBefore('test', 'testBefore', function(d, name) { //停止后续的执行 d.stop(); result.push(name + '-before1'); }) obj.onBefore('test', 'testAfter', function(d, name) { result.push(name + '-before2'); }) obj.on('test', 'testBefore2', function(d, name) { result.push(name + '-after'); }) obj.test('call'); expect(result.join(',')).toBe('call-before1');
stopPropagation和preventDefault控制
var obj = st.attachTrigger({ test: function(name) { result.push(name); } }); obj.onBefore('test', 'testBefore', function(d, name) { result.push(name + '-before1'); //stopPropagation阻止before的回调,preventDefault阻止默认方法 d.stopPropagation().preventDefault(); }) obj.onBefore('test', 'testAfter', function(d, name) { result.push(name + '-before2'); }) obj.on('test', 'testBefore2', function(d, name) { result.push(name + '-after'); }) obj.test('call'); //最终输出第一个before回调和后置回调 expect(result.join(',')).toBe('call-before1,call-after');
更多的例子请参考smartjs上的测试用例