標籤:c style class blog code java
上篇介紹了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上的測試案例