对于需要按设定的时间间隔刷新向用户呈现的部分数据的简单 Web 应用程序,仅使用
setInterval()
从端点获取 JSON 而不是使用适当的轮询框架是否有任何缺点?
举个例子,假设我每 5 秒刷新一次处理作业的状态。
setTimeout
[文档],并始终在收到之前的响应时调用它。这样,您可以避免可能的拥塞或函数堆栈或任何您想要调用的内容,以防请求/响应花费的时间超过您的时间间隔。
所以像这样:
function refresh() {
// make Ajax call here, inside the callback call:
setTimeout(refresh, 5000);
// ...
}
// initial call, or just call refresh directly
setTimeout(refresh, 5000);
可以在最近的浏览器中使用 Promises 实现简单的非阻塞轮询功能:
var sleep = duration => new Promise(resolve => setTimeout(resolve, duration))
var poll = (promiseFn, duration) => promiseFn().then(
sleep(duration).then(() => poll(promiseFn, duration)))
// Greet the World every second
poll(() => new Promise(() => console.log('Hello World!')), 1000)
你可以这样做:
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);
我知道这是一个老问题,但我偶然发现了它,并且以 StackOverflow 的方式做事,我认为我可以改进它。您可能需要考虑类似于“此处描述的内容”的解决方案,称为长轮询。或者另一个解决方案是 WebSockets(WebSockets 的更好实现之一,其主要目标是在所有浏览器上工作)socket.io。 第一个解决方案基本上概括为您发送一个 AJAX 请求并在发送另一个请求之前等待响应,然后一旦响应已交付,就对下一个查询进行排队。
同时,在后端,直到状态发生变化才返回响应。因此,在您的场景中,您将使用一个 while 循环,该循环将持续到状态更改为止,然后将更改后的状态返回到页面。我真的很喜欢这个解决方案。正如上面链接的答案所示,这就是 facebook 所做的(或至少过去做过的)。
socket.io 基本上是 Websockets 的 jQuery,因此无论您的用户使用哪个浏览器,您都可以建立一个套接字连接,将数据推送到页面(根本不需要轮询)。这更接近黑莓的即时通知,如果您想要即时通知,这是最好的解决方案。
,是的,你可以通过调用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....")