对于轮询功能的实现,查找相关的资料,大都是使用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);
以上代码看起来是不是显得冗余和难看,但这是最简单的实现方法。