Javascript 使用 setInterval() 进行简单的连续轮询
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8682622/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using setInterval() to do simplistic continuous polling
提问by Sologoub
For a simple webapp that needs to refresh parts of data presented to the user in set intervals, are there any downsides to just using setInterval() to get a JSON from an endpoint instead of using a proper polling framework?
对于需要以设定的时间间隔刷新呈现给用户的部分数据的简单 web 应用程序,仅使用 setInterval() 从端点获取 JSON 而不是使用适当的轮询框架有什么缺点吗?
For the sake of the example, lets say I'm refreshing status of a processing job every 5 seconds.
就示例而言,假设我每 5 秒刷新一次处理作业的状态。
回答by Felix Kling
From my comment:
从我的评论:
I would use setTimeout
[docs]and always call it when the previous response was received. This way you avoid possible congestion or function stacking or whatever you want to call it, in case a request/response takes longer than your interval.
我会使用setTimeout
[docs]并在收到上一个回复时始终调用它。这样您就可以避免可能的拥塞或函数堆栈或您想调用的任何内容,以防请求/响应花费的时间超过您的时间间隔。
So something like this:
所以像这样:
function refresh() {
// make Ajax call here, inside the callback call:
setTimeout(refresh, 5000);
// ...
}
// initial call, or just call refresh directly
setTimeout(refresh, 5000);
回答by bschlueter
A simple non-blocking poll function can be implemented in recent browsers using Promises:
使用 Promises 在最近的浏览器中可以实现一个简单的非阻塞轮询功能:
var sleep = time => new Promise(resolve => setTimeout(resolve, time))
var poll = (promiseFn, time) => promiseFn().then(
sleep(time).then(() => poll(promiseFn, time)))
// Greet the World every second
poll(() => new Promise(() => console.log('Hello World!')), 1000)
回答by Scen
You can do just like this:
你可以这样做:
var i = 0, loop_length = 50, loop_speed = 100;
function loop(){
i+= 1;
/* Here is your code. Balabala...*/
if (i===loop_length) clearInterval(handler);
}
var handler = setInterval(loop, loop_speed);
回答by th3byrdm4n
I know this is an old question but I stumbled over it, and in the StackOverflow way of doing things I thought I might improve it. You might want to consider a solution similar to what's described herewhich is known as long polling. OR another solution is WebSockets (one of the better implementations of websockets with the primary objective of working on all browsers) socket.io.
我知道这是一个老问题,但我偶然发现了它,在 StackOverflow 的做事方式中,我认为我可以改进它。您可能需要考虑类似于此处描述的解决方案,称为长轮询。或者另一种解决方案是 WebSockets (主要目标是在所有浏览器上工作的 websockets 的更好实现之一)socket.io。
The first solution is basically summarized as you send a single AJAX request and wait for a response before sending an additional one, then once the response has been delivered, queue up the next query.
第一个解决方案基本上总结为您发送一个 AJAX 请求并在发送另一个请求之前等待响应,然后一旦响应被传递,就将下一个查询排队。
Meanwhile, on the backend you don't return a response until the status changes. So, in your scenario, you would utilize a while loop that would continue until the status changed, then return the changed status to the page. I really like this solution. As the answer linked above indicates, this is what facebook does (or at least has done in the past).
同时,在后端,在状态改变之前您不会返回响应。因此,在您的场景中,您将使用一个 while 循环,该循环将一直持续到状态更改,然后将更改的状态返回到页面。我真的很喜欢这个解决方案。正如上面链接的答案所表明的那样,这就是 facebook 所做的(或至少过去所做的)。
socket.io is basically the jQuery of Websockets, so that whichever browser your users are in you can establish a socket connection that can push data to the page (without polling at all). This is closer to a Blackberry's instant notifications, which - if you're going for instant, it's the best solution.
socket.io 基本上是 Websockets 的 jQuery,因此无论您的用户在哪个浏览器中,您都可以建立一个可以将数据推送到页面的套接字连接(根本不需要轮询)。这更接近于黑莓的即时通知,如果您要即时通知,这是最好的解决方案。
回答by allenyllee
Just modify @bschlueter's answer, and yes, you can cancel this poll function by calling cancelCallback()
只需修改@bschlueter 的回答,是的,您可以通过调用取消此轮询功能cancelCallback()
let cancelCallback = () => {};
var sleep = (period) => {
return new Promise((resolve) => {
cancelCallback = () => {
console.log("Canceling...");
// send cancel message...
return resolve('Canceled');
}
setTimeout(() => {
resolve("tick");
}, period)
})
}
var poll = (promiseFn, period, timeout) => promiseFn().then(() => {
let asleep = async(period) => {
let respond = await sleep(period);
// if you need to do something as soon as sleep finished
console.log("sleep just finished, do something...");
return respond;
}
// just check if cancelCallback is empty function,
// if yes, set a time out to run cancelCallback()
if (cancelCallback.toString() === "() => {}") {
console.log("set timout to run cancelCallback()")
setTimeout(() => {
cancelCallback()
}, timeout);
}
asleep(period).then((respond) => {
// check if sleep canceled, if not, continue to poll
if (respond !== 'Canceled') {
poll(promiseFn, period);
} else {
console.log(respond);
}
})
// do something1...
console.log("do something1...");
})
poll(() => new Promise((resolve) => {
console.log('Hello World!');
resolve(); //you need resolve to jump into .then()
}), 3000, 10000);
// do something2...
console.log("do something2....")