js中实现ajax请求轮询,以及避免第一次延迟

Posted nanke_yh

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了js中实现ajax请求轮询,以及避免第一次延迟相关的知识,希望对你有一定的参考价值。

        对于轮询功能的实现,查找相关的资料,大都是使用window setInterval()方法,该方法的语法和用法如下:

Window setInterval() 方法

定义和用法

setInterval() 方法可按照指定的周期(以毫秒计)来调用函数或计算表达式。

setInterval() 方法会不停地调用函数,直到 clearInterval() 被调用或窗口被关闭。由 setInterval() 返回的 ID 值可用作 clearInterval() 方法的参数。

提示: 1000 毫秒= 1 秒。

提示: 如果你只想执行一次可以使用 setTimeout() 方法。

语法

setInterval(code, milliseconds);
setInterval(function, milliseconds, param1, param2, ...)

        看到的很多文章使用都是单独构建一个function然后通过setInterval()调用它。但是有时候有些请求操作获取数据一般立即需要返回用于显示,为此不太好封装成function。那么又该怎么去使用它?

        在我的项目中,需要实现连续两个ajax的请求,作用:第一个request,第二个是get,得到数据后需要进行显示。而get请求需要准备时间,需要轮询请求。那么设计如下:

return $.ajax(
    url: dataport+"/rest/request",
    type: "POST",
    data: postdata,
    contentType:"application/json",
    success: (function(_this) 
       return function(data) 
          if(data.message === 'success')
              console.log("token: "+data.token);
              var webinfo2 = "kind":kindindex,
                              "userid":userid,
                              "token":data.token;
              var postdata2 = JSON.stringify(webinfo2);
              var count = 0 ;      
              //加一个轮询等待机制
              this.timeId = window.setInterval(()=>
                 if(navdata !== 0)
                      console.log("last count,end poling:"+count);
                      window.clearInterval(this.timeId);
                 ;return $.ajax(
                      url: dataport+"/rest/get",
                      type: "POST",
                      data: postdata2,
                      contentType:"application/json",
                      async: true,
                      cache: true,
                      success: function (datas) 
                           count++;
                           console.log("the count is : "+count);
                           navdata = datas.status;//全局变量
                           if (datas.status === 0) 
                              console.log("数据准备中,请等待!");
                              //return _this.$el.find(".data-manage-bottom #data-list").html('<div class="data-managet-warning"><h3>数据准备中,请等待...</h3></div>');
                           
                           else if (datas.status === 2) 
                              return _this.$el.find(".data-manage-bottom #data-list").html('<div class="data-managet-warning"><h3>暂无数据,数据准备失败!</h3></div>');
                           
                           else if (datas.status === 1)                            
                              console.log(datas.url);
                              console.log(datas.url.length);
                              return _this.renderList(datas.url);//显示
                           
                           if(count === 60)//设置5分钟的轮询超时机制
                           
                              navdata = -1;
                              return _this.$el.find(".data-manage-bottom #data-list").html('<div class="data-managet-warning"><h3>数据准备超时,请过段时间再访问!</h3></div>');
                           
                      
                 );
              ,5000);//5秒一次
          
       
   )(this)
);

可以将轮询功能抽象出来为:

 this.timeId = window.setInterval(()=>
                 if(跳出条件)
                      window.clearInterval(this.timeId);
                 ;执行代码块或者函数;,5000);

        这样就比较方便了,不用总是想着去构建function,毕竟很多代码块重新封装成function使用起来很不方便。这里直接将需要轮询执行的代码块放在其中,这样就能够实现了对这部分的重复循环。

        以上的代码,在执行过程中,会发现每次请求需要等待一段时间,往往我们轮询是第一次不需要等待的。那么如何避免第一次延迟呢?

为此网上有很多的解决方法:比如js中函数参数如果是”函数名+()“,则会先执行函数,然后将返回值作为真正的参数。相反参数没加“()”则会被作为一个函数块指针,不先执行。在调用function时写成function();还有说使用递归之类的。但对于我们来说,最简单就是第一次重复执行一下就行了。代码如下:

return $.ajax(
    url: dataport+"/rest/request",
    type: "POST",
    data: postdata,
    contentType:"application/json",
    success: (function(_this) 
        return function(data) 
           if(data.message === 'success')
               console.log("token: "+data.token);
               var webinfo2 = "kind":kindindex,
                  "userid":userid,//webuserInfo1.userid.toString(),
                  "token":data.token;
               var postdata2 = JSON.stringify(webinfo2);

               var count = 0 ;
               //避免第一次延时
               return $.ajax(
                   url: dataport+"/rest/get",
                   type: "POST",
                   data: postdata2,
                   contentType:"application/json",
                   async: true,
                   cache: true,
                   success: function (datas) 
                       count++;
                       console.log("the count is : "+count);
                       navdata = datas.status;
                       if (datas.status === 0) 
                           console.log("数据准备中,请等待!");
                           _this.$el.find(".data-manage-bottom #data-list").html('<div class="data-managet-warning"><h3>数据准备中,请等待...</h3></div>');
                       
                       else if (datas.status === 2) 
                           return _this.$el.find(".data-manage-bottom #data-list").html('<div class="data-managet-warning"><h3>暂无数据,数据准备失败!</h3></div>');
                       
                       else if (datas.status === 1) 
                           console.log(datas.url);
                           console.log(datas.url.length);
                           return _this.renderList(datas.url);
                       
                       //加一个轮询等待机制
                       this.timeId = window.setInterval(()=>
                          if(navdata !== 0)
                            console.log("last count,end poling:"+count);
                            window.clearInterval(this.timeId);
                          ;return $.ajax(
                             url: dataport+"/rest/get",
                             type: "POST",
                             data: postdata2,
                             contentType:"application/json",
                             async: true,
                             cache: true,
                             success: function (datas) 
                               count++;
                               console.log("the count is : "+count);
                               navdata = datas.status;
                               if (datas.status === 0) 
                                 console.log("数据准备中,请等待!");
                                 //return _this.$el.find(".data-manage-bottom #data-list").html('<div class="data-managet-warning"><h3>数据准备中,请等待...</h3></div>');
                               
                               else if (datas.status === 2) 
                                 return _this.$el.find(".data-manage-bottom #data-list").html('<div class="data-managet-warning"><h3>暂无数据,数据准备失败!</h3></div>');
                               
                               else if (datas.status === 1) 
                                 console.log(datas.url);
                                 console.log(datas.url.length);
                                 return _this.renderList(datas.url);
                               
                               if(count === 60)//设置5分钟的轮询超时机制
                               
                                 navdata = -1;
                                 return _this.$el.find(".data-manage-bottom #data-list").html('<div class="data-managet-warning"><h3>数据准备超时,请过段时间再访问!</h3></div>');
                             
                          
                       );
                       ,5000);
                   
               );
            
         
    )(this)
);

这样抽象出来就是:

执行的代码块或函数;

 this.timeId = window.setInterval(()=>
                 if(跳出条件)
                      window.clearInterval(this.timeId);
                 ;执行代码块或者函数;,5000);

以上代码看起来是不是显得冗余和难看,但这是最简单的实现方法。

以上是关于js中实现ajax请求轮询,以及避免第一次延迟的主要内容,如果未能解决你的问题,请参考以下文章

多个 AJAX 请求相互延迟

轮询,长轮询,websocket原理

服务端向客户端推送消息:轮询,长轮询(兼容性好),以及websocket(主流浏览器都支持)

struts中实现ajax的配置信息

在vertx中实现长轮询

代码发布系统二