• 框架基础:ajax设计方案(二)---集成轮询技术


    框架基础:ajax设计方案(二)---集成轮询技术

    上一篇文章介绍了ajax技术核心方法,和跨域的问题(只要后台支持跨域默认post就可以),这篇文章讲解一下使用ajax实现的轮询技术,至于iframe,SSE服务器单向推送,以及webSocket双工通道暂时不涉及

    一些概念:

      短轮询:浏览器通过循环或者setTimeout方法,每隔一段时间往后台发送一次请求,无线循环

      长轮询:不停的向后台请求数据,但是后台如果检测不到数据变动,就会将这个请求挂掉。如果检测到数据变动,就会响应这个请求变动数据

    区别概念:

      长连接:在进行http数据传输的时候,在数据传输层一直开着一个TCP通道,所有请求资源文件都是通过复用这个通道去请求数据,有超时时间

      短连接:如果http进行的短连接,即每次浏览器发送请求,都会创建TCP通道,然后传输完成了再进行销毁,重复操作,消耗很大

    主要区别:

    1. http的长短轮询,通过代码层,向后台请求数据。
    2. Http的长短连接,实际上就是TCP协议传输层是否复用一个TCP协议。

    主要业务方面:及时性比较高的应用(web端聊天系统),或者需要后台等待响应的应用(比如付款,等待完成响应)。

    关键代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    /*
        * 长轮询的实现
        *   a. 业务上只需要得到服务器一次响应的轮询
        *   b. 业务上需要无限次得到服务器响应的轮询
        *
        *   param: url   请求接口地址
        *          data  请求参数
        *          successEvent    成功事件处理
        *          isAll           是否一直请求(例如,等待付款完成业务,只需要请求一次)
        *          timeout         ajax超时时间
        *          timeFrequency   每隔多少时间发送一次请求
        *          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);
                   //业务需求判断,是否只需要得到一次结果
                   if (!isAll) clearTimeout(timer);
               },
               //如果走了error说明该接口有问题,没必要继续下去了
               error:errorEvent,
               timeout:function(){
                   timeoutEvent();
                   setTimeout(function(){
                       tempObj.longPolling(url,data,successEvent,isAll,error,timeoutEvent)
                   },timeFrequency);
               }
           };
           ajax.common(ajaxParam);
       }

    考虑到业务需求,集成了一次isAll参数有2个意义

    1. 聊天系统会要一直需求轮询,不间断的向后台使用数据,所以isAll = true
    2. 等待付款业务只需要得到后台一次响应是否支付成功,所以isAll = false

    稍微提及一下遇到的一些问题:

    问题:

    1
    2
    3
    4
    success:function(date){
         successEvent(data);    //此处使用递归,不停递归自己
         tempObj.longPolling(url,data,successEvent,isAll,error,timeoutEvent);
    },       

    浏览器报错:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    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)

    英文解释:

    超出最大调用堆栈大小。

    问题原因:

    递归调用过多导致的栈溢出问题说明

    问题解释:

    函数调用的参数是通过栈空间来传递的,在调用过程中会占用线程的栈资源。而递归调用,只有走到最后的结束点后函数才能依次退出,而未到达最后的结束点之前,占用的栈空间一直没有释放,如果递归调用次数过多,就可能导致占用的栈资源超过线程的最大值,从而导致栈溢出,导致程序的异常退出。js可以调用自身,这里不停的调用longPolling方法,在方法里面不停的调用自己,导致GC(垃圾回收)一直不释放,越来越大,导致资源超过最大上限,直接崩溃。然后级联一层一层的抛出崩溃信息

    解决方案:

    使用settimeout解决该问题

    方案解释:

    因为Javascript是单线程的,有个排队的处理队列,所以settimeout相当于有一个计时器,不停的向这个队列每隔一段时间塞进一个处理事件。因为这样,相当于longPolling方法每次都走完了,GC就将该方法的资源释放了,然后再执行,再释放。

    代码已集成github:https://github.com/GerryIsWarrior/ajax     点颗星星是我最大的鼓励,下一步研究ajax的上传文件技术(H5的)

    PS:对于轮询这个技术,虽然平时用的少,但是在一些特殊的业务场景能发挥很大的作用。在浏览器,没有完完全全支持H5的境况下,这个还是要考虑的。毕竟H5的那些webSocket还是需要H5兼容的。而且,研究这一块,对原声js,和计算机的一些底层技术还是很有帮助的,像堆栈溢出,不仅仅是前端,后端也会遇到。这样的话,自己底层更夯实,对于以后上层的发展也会有更好的增长。

    【转发自http://www.cnblogs.com/GerryOfZhong/p/6135288.html】

  • 相关阅读:
    一天一个算法:将一个数组中的值按逆序输出
    一天一个算法:求俩个数的最大公约数和最小公倍数
    一天一个算法:给出年、月、日,计算该日是该年的第几天
    一天一个算法:递归计算函数
    一天一个算法:冒泡排序算法
    一天一个算法:猴子吃桃问题
    一天一个算法:求Sn=a+aa+aaa+…+aa…a之和
    一天一个算法:完数
    一天一个算法:水仙花数
    一天一个算法:前言
  • 原文地址:https://www.cnblogs.com/gh0408/p/6275390.html
Copyright © 2020-2023  润新知