对于需要刷新以固定间隔呈现给用户的部分数据的简单webapp,使用setInterval()从端点获取JSON而不是使用适当的轮询框架是否有任何缺点?
为了举例,我假设我每隔5秒刷新一次处理作业的状态。
答案 0 :(得分:45)
来自我的评论:
我会使用setTimeout
[docs]并在收到上一个回复时始终调用它。通过这种方式,您可以避免可能的拥塞或功能堆叠或任何您想要调用它的情况,以防请求/响应时间超过您的间隔。
这样的事情:
function refresh() {
// make Ajax call here, inside the callback call:
setTimeout(refresh, 5000);
// ...
}
// initial call, or just call refresh directly
setTimeout(refresh, 5000);
答案 1 :(得分:9)
可以使用Promises在最近的浏览器中实现简单的非阻塞轮询功能:
sqlite3_prepare_v2
答案 2 :(得分:2)
你可以这样做:
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);
答案 3 :(得分:1)
我知道这是一个老问题,但我偶然发现它,并且在StackOverflow的做事方式中我认为我可以改进它。您可能需要考虑类似于what's described here的解决方案,称为长轮询。或另一个解决方案是WebSockets(websockets的一个更好的实现,其主要目标是在所有浏览器上工作)socket.io。
第一个解决方案基本上是在发送一个AJAX请求并在发送另一个请求之前等待响应时进行总结,然后在响应发送后,排队下一个查询。
同时,在后端,在状态发生变化之前,您不会返回响应。因此,在您的方案中,您将使用while循环,该循环将持续到状态更改,然后将更改后的状态返回到页面。我非常喜欢这个解决方案。正如上面的答案所表明的那样,这就是facebook所做的事情(或者至少在过去做过)。
socket.io基本上就是Websockets的jQuery,所以无论你的用户在哪个浏览器中,你都可以建立一个可以将数据推送到页面的套接字连接(根本没有轮询)。这更接近黑莓的即时通知,如果你是即时通知,它是最好的解决方案。
答案 4 :(得分:0)
只需修改@bschlueter's answer,是的,您可以通过调用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....")