框架基礎:ajax設計方案(二)---集成輪詢技術

出處:http://www.cnblogs.com/GerryOfZhong/p/6135288.html
作者:半個詩人


上一篇(框架基礎:ajax設計方案(一)---集成核心請求)文章介紹了ajax技術核心方法,和跨域的問題(只要后臺支持跨域默認post就可以),這篇文章講解一下使用ajax實現(xiàn)的輪詢技術,至于iframe,SSE服務器單向推送,以及webSocket雙工通道暫時不涉及。

一些概念:

  • 短輪詢:瀏覽器通過循環(huán)或者setTimeout方法,每隔一段時間往后臺發(fā)送一次請求,無線循環(huán)
  • 長輪詢:不停的向后臺請求數(shù)據(jù),但是后臺如果檢測不到數(shù)據(jù)變動,就會將這個請求掛掉。如果檢測到數(shù)據(jù)變動,就會響應這個請求變動數(shù)據(jù)

區(qū)別概念:

  • 長連接:在進行http數(shù)據(jù)傳輸?shù)臅r候,在數(shù)據(jù)傳輸層一直開著一個TCP通道,所有請求資源文件都是通過復用這個通道去請求數(shù)據(jù),有超時時間
  • 短連接:如果http進行的短連接,即每次瀏覽器發(fā)送請求,都會創(chuàng)建TCP通道,然后傳輸完成了再進行銷毀,重復操作,消耗很大

主要區(qū)別:

  • http的長短輪詢,通過代碼層,向后臺請求數(shù)據(jù)。
  • http的長短連接,實際上就是TCP協(xié)議傳輸層是否復用一個TCP協(xié)議。

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

關鍵代碼:

/*
    * 長輪詢的實現(xiàn)
    *   a. 業(yè)務上只需要得到服務器一次響應的輪詢
    *   b. 業(yè)務上需要無限次得到服務器響應的輪詢
    *
    *   param: url   請求接口地址
    *          data  請求參數(shù)
    *          successEvent    成功事件處理
    *          isAll           是否一直請求(例如,等待付款完成業(yè)務,只需要請求一次)
    *          timeout         ajax超時時間
    *          timeFrequency   每隔多少時間發(fā)送一次請求
    *          error           錯誤事件
    *          timeout         超時處理
    * */
   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è)務需求判斷,是否只需要得到一次結(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è)務需求,集成了一次isAll參數(shù)有2個意義
聊天系統(tǒng)會要一直需求輪詢,不間斷的向后臺使用數(shù)據(jù),所以isAll = true
等待付款業(yè)務只需要得到后臺一次響應是否支付成功,所以isAll = false

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

問題:

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

瀏覽器報錯:

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)用過多導致的棧溢出問題說明

問題解釋:
函數(shù)調(diào)用的參數(shù)是通過??臻g來傳遞的,在調(diào)用過程中會占用線程的棧資源。而遞歸調(diào)用,只有走到最后的結(jié)束點后函數(shù)才能依次退出,而未到達最后的結(jié)束點之前,占用的棧空間一直沒有釋放,如果遞歸調(diào)用次數(shù)過多,就可能導致占用的棧資源超過線程的最大值,從而導致棧溢出,導致程序的異常退出。js可以調(diào)用自身,這里不停的調(diào)用longPolling方法,在方法里面不停的調(diào)用自己,導致GC(垃圾回收)一直不釋放,越來越大,導致資源超過最大上限,直接崩潰。然后級聯(lián)一層一層的拋出崩潰信息

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

方案解釋:
因為Javascript是單線程的,有個排隊的處理隊列,所以settimeout相當于有一個計時器,不停的向這個隊列每隔一段時間塞進一個處理事件。因為這樣,相當于longPolling方法每次都走完了,GC就將該方法的資源釋放了,然后再執(zhí)行,再釋放。

代碼已集成github:GerryIsWarrior/ajax,點顆星星是我最大的鼓勵,下一步研究ajax的上傳文件技術(H5的)

PS:對于輪詢這個技術,雖然平時用的少,但是在一些特殊的業(yè)務場景能發(fā)揮很大的作用。在瀏覽器,沒有完完全全支持H5的境況下,這個還是要考慮的。畢竟H5的那些webSocket還是需要H5兼容的。而且,研究這一塊,對原聲js,和計算機的一些底層技術還是很有幫助的,像堆棧溢出,不僅僅是前端,后端也會遇到。這樣的話,自己底層更夯實,對于以后上層的發(fā)展也會有更好的增長。

本文完!


在學習過程如果有任何疑問,請來極樂網(wǎng)(http://www.dreawer.com提問,或者掃描下方二維碼,關注極樂官方微信,在平臺下方留言~

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,008評論 25 709
  • 從三月份找實習到現(xiàn)在,面了一些公司,掛了不少,但最終還是拿到小米、百度、阿里、京東、新浪、CVTE、樂視家的研發(fā)崗...
    時芥藍閱讀 42,793評論 11 349
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,551評論 19 139
  • “古之教者,教以人倫。后世記誦詞章之習起,而先王之教亡。今教童子,惟當以孝、悌、忠、信、禮、義、廉、恥為專務。其栽...
    沐云齋閱讀 1,461評論 0 2
  • 水手張叁閱讀 356評論 0 0

友情鏈接更多精彩內(nèi)容