本篇介紹0.1版中最后一個特性,FlowController;同時也對第一版總結一下,因為近兩年全部都是在搞前端,都是做一些js框架類的東西,也做了不少有意思的功能,做smartjs對我來說一個是對自己做一個總結,也希望分享一些東西給大家借鑒。
而對smartjs的來說,整體思想都並不是為了實現什么功能、特效和內容。而是希望體現一些前端編程模式或者思想上的內容,這次的0.1版本中,主要體現了一些面向切面編程、非侵入式編程、異步編程,生命周期控制的一些思想。包括后續的oop的內容,基於策略的數據管理,模型驅動,類型驅動等等都是想給前端開發中注入一些特別點的內容。
FlowController
流程或者生命周期管理器。控制流程的走向,流程擴展,注入控制等等;FlowController是基於trigger封裝,具有所有trigger的特性;
接口方法
var flow = { node1 : function(e,arg,...){} }; //流程控制初始化 flowController({ flow : flow, order : ["node1"], mode : "", trigger : true | {mode : "",iFace : {}} }) //啟動流程 flow.boot(arg,...); //根據指定的流程節點啟動 flow.bootWithStart("start",[args])
參數講解
- flow :流程定義
- order : 流程執行順序
- mode :流程模式,默認為promiseEvent模式;simple:簡單模式
- trigger : trigger的設置,詳細見上篇trigger api說明
在流程中的e參數,與trigger一樣,只是多出了幾個流程控制方法方法
e.end() : 停止流程方法
e.next(nextNode, pass, args) : 指定下個節點方法;
- nextNode:下個節點名稱,可以不在流程定義order設置中
- pass: 可選,略過的流程節點數,只在nextNode指向的非定義的流程節點有效
- args:可選,指定nextNode的方法參數
e.changeArgs([]): 改變后續流程的方法參數
e.recoverArgs(): 回復原始方法參數,與changeArgs對應;
另外,需要注意的是
e.stop() : 與trigger的效果一樣,停止方法的執行,這里是停止當前節點的后續執行,但不影響 流程的后續執行
使用樣例
簡單模式
var flow = st.flowController({ flow: { init: function(name, op) { log(name, 'init'); }, render: function(name, op) { log('render'); }, complete: function(name, op) { log('complete'); } }, order: ["init", "render", "complete"], mode: "simple" }) flow.boot("boot"); expect(arr + '').toBe('boot,init,render,complete');
普通模式
以一個見的控件渲染為例子,正常的有init,render,complete三個節點,還有兩個非標准流程節點buildInput和cancel。在init節點中根據name不同還有做流程走向控制
//一個簡單的控件渲染流程 var promiseFlow = st.flowController({ flow: { init: function(e, name, op) { setTimeout(function() { log(name, 'init'); //根據name判斷下個流程 if (name === 'input') //改變下個流程的參數 e.next("buildInput", [op.type]); else if (name === 'cancel') e.next('cancel') e.resolve(); }, 100) return e.promise(); }, //非標准流程中的節點 buildInput: function(e, type) { setTimeout(function() { log('buildInput'); e.resolve(type); }, 100) return e.promise(); }, //非標准流程中的節點 cancel: function(e) { setTimeout(function() { log('cancel'); //流程結束 e.end().resolve(); }, 100) return e.promise(); }, render: function(e, name, op) { //值傳遞測試 e.result && log(e.result); log('render'); }, complete: function(e, name, op) { log('complete'); } }, order: ["init", "render", "complete"] }); //div控件走正常流程 $.when(promiseFlow.boot("div")).done(function() { expect(arr + '').toBe('div,init,render,complete'); }) //input進入非標准流程 $.when(promiseFlow.boot("input", { type: 'text' })).done(function() { expect(arr + '').toBe('input,init,buildInput,text,render,complete'); }); //end測試 $.when(promiseFlow.boot("end")).done(function() { expect(arr + '').toBe('end,init,cancel'); })
trigger注入方法例子
var triggerFlow = st.flowController({ flow: { init: function(e, name, op) { setTimeout(function() { log(name, 'init'); e.resolve(); }, 100) return e.promise(); }, render: function(e, name, op) { log('render'); }, complete: function(e, name, op) { log('complete'); } }, order: ["init", "render", "complete"], trigger: true }); it("trigger", function(testCall) { //init節點注入前置方法 triggerFlow.onBefore("init", "initBefore", function(e, name, op) { log('initBefore'); }, "once"); //init節點注入后置方法 triggerFlow.on("init", "initAfter", function(e, name, op) { setTimeout(function() { log('initAfter'); e.resolve(); }, 100) return e.promise(); }, "once"); $.when(triggerFlow.boot("div")).done(function() { expect(arr + '').toBe('initBefore,div,init,initAfter,render,complete'); testCall(); }) }) it("trigger - next", function(testCall) { //init中注入方法,跳入后續節點 triggerFlow.onBefore("init", "initBefore", function(e, name, op) { setTimeout(function() { log('initBefore'); e.next('complete').resolve(); }, 100) return e.promise(); }, "once"); $.when(triggerFlow.boot("div")).done(function() { expect(arr + '').toBe('initBefore,div,init,complete'); testCall(); }) }) //注入方法結束節點 it("trigger - end", function(testCall) { triggerFlow.onBefore("init", "initBefore", function(e, name, op) { setTimeout(function() { log('initBefore'); e.end().resolve(); }, 100) return e.promise(); }, "once"); $.when(triggerFlow.boot("div")).done(function() { expect(arr + '').toBe('initBefore'); testCall(); }) })
還有很多的流程控制的例子就不一一介紹了,請參考smartjs上的測試用例
