js中的嵌套函數用的很多,很牛叉,那為何要平面化?
- 易懂(自己及他人)
- 易修改(自己及他人)
平時Ajax調用寫法(基於jQuery)
$.post('url', jsonObj, function (data) { if(data) { var tips = $.ligerDialog.tip({ title: 'Tip', content: 'Operation successful!' }); setTimeout(function () { tips.close(); }, 2000); } else { var tips = $.ligerDialog.tip({ title: 'Tip', content: 'Operation Failed!' }); setTimeout(function () { tips.close(); }, 2000); } } );
缺點是什么?
- 函數嵌套后,理解起來比較吃力
- 函數嵌套后,一行函數調用寫成了很多行,很容易因為逗號、括號等造成語法錯誤
- jQuery和liger在應用代碼中強耦合,要是以后要更換UI框架,需要進行地毯式搜索...
加入延遲特性 - Deferred
var ajaxHandler = $.post('url', params); ajaxHandler.done(checkServerResponse); var checkServerResponse=function(result) { if(result) { var tips = $.ligerDialog.tip({ title: 'Tip', content: 'Operation successful!' }); setTimeout(function () { tips.close(); }, 2000); } else { var tips = $.ligerDialog.tip({ title: 'Tip', content: 'Operation Failed!' }); setTimeout(function () { tips.close(); }, 2000); } }
釋疑:
- 改后的js與先前的沒有很大區別:如果js采用了OO方式編寫,再來看這段代碼就很清晰了(可以簡單的把checkServerResponse理解為一個private的class方法,這樣會很容易理解編寫意圖)
- 要是有多個ajax請求呢?可以寫成$.when($.post('url1'), $.post('url2')).done(this.checkServerResponse);類似於合並的意思,並且checkServerResponse函數的參數是2個,分別對應2個ajax請求的result
- 要是有多個后續請求呢?可以寫成$.when($.post(url)).then(handler1).then(handler2).done(successHandler).always(alwaysHandler).fail(failHandler);
用jQuery的事件來解耦 - 不依賴具體技術
先要注冊事件:
$(document).on("saveSuccess", onSaveSuccess);
$(document).on("saveFail", onSaveFail);
然后改造checkServerResponse函數:
var checkServerResponse= function (result) { if (result) $(document).trigger("saveSuccess"); else $(document).trigger("saveFail"); }
好處:
邏輯代碼具體不依賴於具體技術,比如上面的onSaveSuccess和onSaveFail,可以是下面的ligerUI:
onSaveSuccess: function () { var tips = $.ligerDialog.tip({ title: 'Tip', content: 'OK!' }); setTimeout(function () { tips.close(); }, 2000); }, onSaveFail: function () { var tips = $.ligerDialog.tip({ title: 'Tip', content: 'Fail!' }); setTimeout(function () { tips.close(); }, 2000); }
也可以是下面的:
onSaveSuccess: function () { alert("OK"); }, onSaveFail: function () { alert("Fail"); },
其實就是接口隔離的原理。
用Pub/Sub模式來解耦 - 不依賴具體技術
這種方式比起上面jQuery原生的事件處理方式更加專業,比如:amplify。
使用方式就看基本類似,如下:
amplify.subscribe("saveSuccess", this.onSaveSuccess); amplify.subscribe("saveFail", this.onSaveFail); checkServerResponse: function (result) { if (result) amplify.publish("saveSuccess"); else amplify.publish("saveFail"); }
amplify比jQuery原生的事件好的地方在於amplify支持優先級,並且可以在訂閱函數中控制是否繼續執行后續的訂閱函數,具體用法大家可以參考amplify官網。