新型網站開發:從服務端取數據的最簡方法

本文章轉載于搜狗測試

開發網站,前端頁面需要從服務器端取數據,怎么取?你可能在想,這還不簡單,有比ajax更簡單的嗎?

jquery把此過程封裝到一個接口函數$.ajax(…)(以及幾個糖方法$.get、$.post)里,貌似已經很好用了,難道還能更好用嗎?!

我們來仔細分析一下這個事情,看我們的工作量能不能減少。我們需要從服務器取數據,就在前端利用$.ajax構造一個ajax請求,為了發送這個請求,我們必須設置好url以及拼裝好參數。服務器端呢,處理這個url,解析這個請求傳來的參數,然后把參數傳給適當的方法來生成響應數據。

我們一次次的重復這個參數的組裝成包和拆包解包過程(在前端把參數組裝成包,在服務器端把參數從包中解析出來),我們寫了很多代碼,就是為了調用一下服務器端一個方法,并把方法的返回值作為響應打給前端。

我們有沒有機會改進這個過程,把這些重復工作省掉。

在我們設計如何把這些重復工作省掉之前,我們先想想,前端調取后端一個方法來得到數據,最簡單能簡單到什么程度?

比如我們后端有一個類,類里有一個方法:

classuserFactroy{

functiongetUserInfoById(userId){

return{ username:’某某某’ }

}

}

前端在調用的時候,需要提供如下三個信息:1、類名;2、類里的方法名;3、傳送給方法的參數(在本例中就是userId)

類名和方法名可以用一個字符串來描述,參數嘛,調用方法時可能需要傳遞多個,故參數用一個數組表示

故前端為了獲取某id的用戶信息可以如下調用:

var result =MyCall(類名,方法名,參數列表)

本例中就是:

var userInfo=MyCall(“userFactroy”,”getUserInfoById”,[userId])

當然,由于js的單線程特性,我們不應該同步獲取函數返回結果,否則頁面就卡住了。實戰中應該使用callback或promise來取回結果。

callback版:

MyCall(“userFactroy”,”getUserInfoById”,[userId],function(userInfo){

})

promise版:

MyCall(“userFactroy”,”getUserInfoById”,[userId])

.then(function(userInfo){

})

不用我說,這樣的MyCall函數(還有服務端對應的接收代碼)大家肯定也會實現,這個思想本質上就是在前端和后端,分別寫一個【樁函數】,由它們來完成所有的參數打包以及解包過程,其他人只需要專注實現具體方法即可,本例中就是只顧安心實現getUserInfoById即可。

扯了這么多,現在開始說關鍵的了

如果本貼就是為了推廣如何寫或應該寫MyCall這樣的樁函數,那就不用寫本貼了,太小兒科了,呵呵O(∩_∩)O~

我們有更好的想法:

用過js模塊化嗎?就是AMD或CMD規范。沒用過?趕快百度查看一下,項目中趕快用呀!

這兩個規范,以及服務器端的CommonJS規范都有一個共同思想:

用require導入模塊,然后再使用,例如:

var userFactory=require(‘path/to/ userFactory’);

var userInfo=userFactory.getUserInfoById(userId);

里面的require很像python的import、c/c++的include、c#的using不是嗎?

我們就以前端使用CMD規范為例吧,這時你一般就是使用sea.js(一個實現了CMD規范的前端js模塊加載器)加載器,

當你在前端js中寫上如上代碼,seajs就會到路經path/to/userFactory處下載這個文件,最后也是在瀏覽器端運行這個getUserInfoById的函數實現代碼。除非getUserInfoById是純前端代碼,否則肯定會出錯。

我們能照樣使用這個形式,在前端調用userFactory.getUserInfoById,但這個函數卻還是在服務器端執行(比如,getUserInfoById在執行過程中,調用了查數據庫等操作),執行完后,函數的返回值依然能在前端得到嗎?

如果實現了,那這不就最大化的簡化了從服務端獲取數據的代碼量了嗎。另外,如果你服務器端是用node.js開發的話,你更會有一種前后端統一的感覺,因為后端js代碼在調用getUserInfoById函數的形式(代碼書寫的樣子)和前端是一樣(雖然本質上不一樣)

經過思考,在不干擾seajs中原本require方法使用的情況下,確實可以利用這個require來實現我們的目標,技術關鍵點就是,截獲seajs下載path/to/userFactory.js的請求(不要讓seajs真的把userFactory源碼下載下來了),應答一個自己構造的響應,這個響應是一個符合cmd規范的js模塊,并exports出所有userFatory所有方法,偽代碼大致如下:

varmoduleName =path.basename(req.originalUrl.split('?')[0],'.js');

varmodulePath = getModulePath(moduleName);

varm = require(modulePath);

varfunctionNames = [];

for(finm) {

if(typeofm[f] ==='function'){

functionNames.push(f);

}

}

res.send('define(function(require,exports,module){var_require=require("_require");'+ functionNames.map(function(f) {return'exports.'+ f +'=function(){return_require.call(null,"'+ moduleName +'","'+ f +'",arguments)}'}).join(';') +'})');

然后,我們在_require.js中實現我們打包參數的所謂【樁函數】:

define(function(require, exports, module){

varq = require('q');

module.exports =function() {

varargs = Array.prototype.slice.call(arguments);

args[2] =Array.prototype.slice.call(args[2]);

varparams = args[2];

vardefer = q.defer();

$.ajax({ url:'/call/',

type:'POST',

data: JSON.stringify(args)

})

.then(function(result) {

varerr = result.shift();

if(err) {

defer.reject(err);

}

else{

defer.resolve(result.length > 1 ? result : result[0]);

}

},function(err) {

defer.reject(err);

});

returndefer.promise;

}

});

至于,服務器的【樁函數】怎么寫,本篇就不再展開講了,本質上就是根據_require.js發送的ajax里的參數,提取類名,方法名,以及調用方法需要的參數,來調用服務器端對應類的類方法,并取回結果,然后把結果發送給瀏覽器。

小結:說道最后,取數據在底層還是使用ajax,這個你跑不脫,你肯定要利用瀏覽器提供的支持,來做你的事兒,我們改變的是獲取服務器數據的代碼書寫方法,我們利用模塊化js規范里的require,在不干擾其本來用法的情況下,讓它也成了獲取服務器端數據的方式,這樣可大大提高開發效率。獲取服務器端數據變得簡單的不能再簡單。

另外,你可能對這種調用服務器里函數的方式感覺一絲不安全,不過這是另一個問題,你的安全檢查大可在服務器端的【樁函數】里搞,呵呵O(∩_∩)O~

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,825評論 6 546
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,814評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,980評論 0 384
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 64,064評論 1 319
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,779評論 6 414
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,109評論 1 330
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,099評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,287評論 0 291
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,799評論 1 338
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,515評論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,750評論 1 375
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,221評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,933評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,327評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,667評論 1 296
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,492評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,703評論 2 380

推薦閱讀更多精彩內容

  • Node.js是目前非常火熱的技術,但是它的誕生經歷卻很奇特。 眾所周知,在Netscape設計出JavaScri...
    w_zhuan閱讀 3,636評論 2 41
  • @轉自GitHub 介紹js的基本數據類型。Undefined、Null、Boolean、Number、Strin...
    YT_Zou閱讀 1,184評論 0 0
  • 1.幾種基本數據類型?復雜數據類型?值類型和引用數據類型?堆棧數據結構? 基本數據類型:Undefined、Nul...
    極樂君閱讀 5,566評論 0 106
  • 毛病是養成的不良習慣 為什么改掉毛病沒有養成時那樣簡單 吸毒是填補空虛的行為 為什么吸毒的人堅信自己絕不會上癮 人...
    octopusGZ閱讀 225評論 0 0
  • 首先過了一遍劇本。 確定以下幾點: 1. 以后開會討論一些需要花費時間討論的東西。 2. 誰排戲的時候沒來,可以通...
    小池水閱讀 249評論 0 1