框架基礎(chǔ):ajax設(shè)計(jì)方案(二)---集成輪詢技術(shù)

出處:http://www.cnblogs.com/GerryOfZhong/p/6135288.html
作者:半個(gè)詩(shī)人


上一篇(框架基礎(chǔ):ajax設(shè)計(jì)方案(一)---集成核心請(qǐng)求)文章介紹了ajax技術(shù)核心方法凳枝,和跨域的問題(只要后臺(tái)支持跨域默認(rèn)post就可以)跋核,這篇文章講解一下使用ajax實(shí)現(xiàn)的輪詢技術(shù),至于iframe蹋订,SSE服務(wù)器單向推送刻伊,以及webSocket雙工通道暫時(shí)不涉及

一些概念:

  • 短輪詢:瀏覽器通過循環(huán)或者setTimeout方法智什,每隔一段時(shí)間往后臺(tái)發(fā)送一次請(qǐng)求讼呢,無(wú)線循環(huán)
  • 長(zhǎng)輪詢:不停的向后臺(tái)請(qǐng)求數(shù)據(jù)悦屏,但是后臺(tái)如果檢測(cè)不到數(shù)據(jù)變動(dòng)键思,就會(huì)將這個(gè)請(qǐng)求掛掉甫贯。如果檢測(cè)到數(shù)據(jù)變動(dòng),就會(huì)響應(yīng)這個(gè)請(qǐng)求變動(dòng)數(shù)據(jù)

區(qū)別概念:

  • 長(zhǎng)連接:在進(jìn)行http數(shù)據(jù)傳輸?shù)臅r(shí)候赔桌,在數(shù)據(jù)傳輸層一直開著一個(gè)TCP通道渴逻,所有請(qǐng)求資源文件都是通過復(fù)用這個(gè)通道去請(qǐng)求數(shù)據(jù),有超時(shí)時(shí)間
  • 短連接:如果http進(jìn)行的短連接雪位,即每次瀏覽器發(fā)送請(qǐng)求梨撞,都會(huì)創(chuàng)建TCP通道,然后傳輸完成了再進(jìn)行銷毀时肿,重復(fù)操作港粱,消耗很大

主要區(qū)別:

  • http的長(zhǎng)短輪詢,通過代碼層锈颗,向后臺(tái)請(qǐng)求數(shù)據(jù)咪惠。
  • http的長(zhǎng)短連接淋淀,實(shí)際上就是TCP協(xié)議傳輸層是否復(fù)用一個(gè)TCP協(xié)議朵纷。

主要業(yè)務(wù)方面:及時(shí)性比較高的應(yīng)用(web端聊天系統(tǒng)),或者需要后臺(tái)等待響應(yīng)的應(yīng)用(比如付款鞋仍,等待完成響應(yīng))搅吁。

關(guān)鍵代碼:

/*
    * 長(zhǎng)輪詢的實(shí)現(xiàn)
    *   a. 業(yè)務(wù)上只需要得到服務(wù)器一次響應(yīng)的輪詢
    *   b. 業(yè)務(wù)上需要無(wú)限次得到服務(wù)器響應(yīng)的輪詢
    *
    *   param: url   請(qǐng)求接口地址
    *          data  請(qǐng)求參數(shù)
    *          successEvent    成功事件處理
    *          isAll           是否一直請(qǐng)求(例如落午,等待付款完成業(yè)務(wù)溃斋,只需要請(qǐng)求一次)
    *          timeout         ajax超時(shí)時(shí)間
    *          timeFrequency   每隔多少時(shí)間發(fā)送一次請(qǐng)求
    *          error           錯(cuò)誤事件
    *          timeout         超時(shí)處理
    * */
   longPolling:function(url,data,successEvent,isAll,timeout,timeFrequency,errorEvent,timeoutEvent){
       var ajaxParam ={
           time:timeout,
           type:"post",
           url:url,
           data:data,
           async:false,
           success:function(date){
               successEvent(data);
               var timer = setTimeout(
                   function(){
                       tempObj.longPolling(url,data,successEvent,isAll,error,timeoutEvent);
                   },timeFrequency);
               //業(yè)務(wù)需求判斷吸申,是否只需要得到一次結(jié)果
               if (!isAll) clearTimeout(timer);
           },
           //如果走了error說明該接口有問題,沒必要繼續(xù)下去了
           error:errorEvent,
           timeout:function(){
               timeoutEvent();
               setTimeout(function(){
                   tempObj.longPolling(url,data,successEvent,isAll,error,timeoutEvent)
               },timeFrequency);
           }
       };
       ajax.common(ajaxParam);
   }

考慮到業(yè)務(wù)需求梳侨,集成了一次isAll參數(shù)有2個(gè)意義
聊天系統(tǒng)會(huì)要一直需求輪詢走哺,不間斷的向后臺(tái)使用數(shù)據(jù)聚凹,所以isAll = true
等待付款業(yè)務(wù)只需要得到后臺(tái)一次響應(yīng)是否支付成功,所以isAll = false

稍微提及一下遇到的一些問題:

問題:

success:function(date){
     successEvent(data);    //此處使用遞歸彼哼,不停遞歸自己
     tempObj.longPolling(url,data,successEvent,isAll,error,timeoutEvent);
},   

瀏覽器報(bào)錯(cuò):

Uncaught RangeError: Maximum call stack size exceeded.
    at Object.common (ajax-1.2.js:202)
    at Object.longPolling (ajax-1.2.js:280)
    at Object.success (ajax-1.2.js:266)
    at XMLHttpRequest.xhr.onload (ajax-1.2.js:160)
    at Object.common (ajax-1.2.js:202)
    at Object.longPolling (ajax-1.2.js:280)
    at Object.success (ajax-1.2.js:266)
    at XMLHttpRequest.xhr.onload (ajax-1.2.js:160)
    at Object.common (ajax-1.2.js:202)
    at Object.longPolling (ajax-1.2.js:280)
common @ ajax-1.2.js:202
longPolling @ ajax-1.2.js:280
success @ ajax-1.2.js:266
xhr.onload @ ajax-1.2.js:160
(anonymous) @ index.html:42
(anonymous) @ index.html:43
 
ajax-1.2.js:202 Uncaught RangeError: Maximum call stack size exceeded.
    at Object.common (ajax-1.2.js:202)
    at Object.longPolling (ajax-1.2.js:280)
    at Object.success (ajax-1.2.js:266)
    at XMLHttpRequest.xhr.onload (ajax-1.2.js:160)
    at Object.common (ajax-1.2.js:202)
    at Object.longPolling (ajax-1.2.js:280)
    at Object.success (ajax-1.2.js:266)
    at XMLHttpRequest.xhr.onload (ajax-1.2.js:160)
    at Object.common (ajax-1.2.js:202)
    at Object.longPolling (ajax-1.2.js:280)

英文解釋:
超出最大調(diào)用堆棧大小敢朱。

問題原因:
遞歸調(diào)用過多導(dǎo)致的棧溢出問題說明

問題解釋:
函數(shù)調(diào)用的參數(shù)是通過椖ο梗空間來傳遞的,在調(diào)用過程中會(huì)占用線程的棧資源蚓哩。而遞歸調(diào)用上渴,只有走到最后的結(jié)束點(diǎn)后函數(shù)才能依次退出,而未到達(dá)最后的結(jié)束點(diǎn)之前曹阔,占用的椄襞空間一直沒有釋放,如果遞歸調(diào)用次數(shù)過多抓韩,就可能導(dǎo)致占用的棧資源超過線程的最大值,從而導(dǎo)致棧溢出园蝠,導(dǎo)致程序的異常退出彪薛。js可以調(diào)用自身,這里不停的調(diào)用longPolling方法少态,在方法里面不停的調(diào)用自己易遣,導(dǎo)致GC(垃圾回收)一直不釋放,越來越大侨歉,導(dǎo)致資源超過最大上限揩魂,直接崩潰。然后級(jí)聯(lián)一層一層的拋出崩潰信息

解決方案:
使用settimeout解決該問題

方案解釋:
因?yàn)镴avascript是單線程的牵舵,有個(gè)排隊(duì)的處理隊(duì)列倦挂,所以settimeout相當(dāng)于有一個(gè)計(jì)時(shí)器,不停的向這個(gè)隊(duì)列每隔一段時(shí)間塞進(jìn)一個(gè)處理事件没炒。因?yàn)檫@樣犯戏,相當(dāng)于longPolling方法每次都走完了,GC就將該方法的資源釋放了,然后再執(zhí)行假颇,再釋放笨鸡。

代碼已集成github:GerryIsWarrior/ajax坦冠,點(diǎn)顆星星是我最大的鼓勵(lì)哥桥,下一步研究ajax的上傳文件技術(shù)(H5的)

PS:對(duì)于輪詢這個(gè)技術(shù),雖然平時(shí)用的少判呕,但是在一些特殊的業(yè)務(wù)場(chǎng)景能發(fā)揮很大的作用送滞。在瀏覽器,沒有完完全全支持H5的境況下边涕,這個(gè)還是要考慮的褂微。畢竟H5的那些webSocket還是需要H5兼容的。而且式撼,研究這一塊肥矢,對(duì)原聲js甘改,和計(jì)算機(jī)的一些底層技術(shù)還是很有幫助的,像堆棧溢出十艾,不僅僅是前端,后端也會(huì)遇到忘嫉。這樣的話庆冕,自己底層更夯實(shí),對(duì)于以后上層的發(fā)展也會(huì)有更好的增長(zhǎng)访递。

本文完!


在學(xué)習(xí)過程如果有任何疑問惭载,請(qǐng)來極樂網(wǎng)(http://www.dreawer.com提問描滔,或者掃描下方二維碼,關(guān)注極樂官方微信券腔,在平臺(tái)下方留言~

極樂官方微信二維碼
極樂官方微信二維碼

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末茎芋,一起剝皮案震驚了整個(gè)濱河市田弥,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌偷厦,老刑警劉巖只泼,帶你破解...
    沈念sama閱讀 222,627評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異弥咪,居然都是意外死亡十绑,警方通過查閱死者的電腦和手機(jī)本橙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,180評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來贷币,“玉大人亏狰,你說我怎么就攤上這事∽止埽” “怎么了?”我有些...
    開封第一講書人閱讀 169,346評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)硫戈。 經(jīng)常有香客問我下硕,道長(zhǎng)梭姓,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,097評(píng)論 1 300
  • 正文 為了忘掉前任罪既,我火速辦了婚禮铡恕,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘驹针。我一直安慰自己诀艰,他們只是感情好其垄,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,100評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著撤防,像睡著了一般棒口。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上漾肮,一...
    開封第一講書人閱讀 52,696評(píng)論 1 312
  • 那天克懊,我揣著相機(jī)與錄音,去河邊找鬼墙懂。 笑死扮念,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的巧勤。 我是一名探鬼主播弄匕,決...
    沈念sama閱讀 41,165評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼迁匠,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了儒搭?” 一聲冷哼從身側(cè)響起芙贫,我...
    開封第一講書人閱讀 40,108評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤磺平,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后拣挪,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,646評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,709評(píng)論 3 342
  • 正文 我和宋清朗相戀三年笼平,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了舔痪。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,861評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡夺英,死狀恐怖痛悯,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情驯耻,我是刑警寧澤炒考,帶...
    沈念sama閱讀 36,527評(píng)論 5 351
  • 正文 年R本政府宣布霎迫,位于F島的核電站,受9級(jí)特大地震影響知给,放射性物質(zhì)發(fā)生泄漏瓤帚。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,196評(píng)論 3 336
  • 文/蒙蒙 一涩赢、第九天 我趴在偏房一處隱蔽的房頂上張望戈次。 院中可真熱鬧,春花似錦筒扒、人聲如沸怯邪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,698評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)悬秉。三九已至,卻和暖如春冰蘑,著一層夾襖步出監(jiān)牢的瞬間和泌,已是汗流浹背祠肥。 一陣腳步聲響...
    開封第一講書人閱讀 33,804評(píng)論 1 274
  • 我被黑心中介騙來泰國(guó)打工武氓, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人仇箱。 一個(gè)月前我還...
    沈念sama閱讀 49,287評(píng)論 3 379
  • 正文 我出身青樓县恕,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親工碾。 傳聞我的和親對(duì)象是個(gè)殘疾皇子弱睦,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,860評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,325評(píng)論 25 707
  • 從三月份找實(shí)習(xí)到現(xiàn)在,面了一些公司渊额,掛了不少况木,但最終還是拿到小米垒拢、百度、阿里火惊、京東求类、新浪、CVTE屹耐、樂視家的研發(fā)崗...
    時(shí)芥藍(lán)閱讀 42,278評(píng)論 11 349
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理尸疆,服務(wù)發(fā)現(xiàn),斷路器惶岭,智...
    卡卡羅2017閱讀 134,716評(píng)論 18 139
  • “古之教者寿弱,教以人倫。后世記誦詞章之習(xí)起按灶,而先王之教亡症革。今教童子,惟當(dāng)以孝鸯旁、悌噪矛、忠、信铺罢、禮艇挨、義、廉韭赘、恥為專務(wù)缩滨。其栽...
    沐云齋閱讀 1,208評(píng)論 0 2
  • 水手張叁閱讀 315評(píng)論 0 0