使用setInterval()进行简单的连续轮询

时间:2011-12-30 18:21:13

标签: javascript ajax setinterval polling

对于需要刷新以固定间隔呈现给用户的部分数据的简单webapp,使用setInterval()从端点获取JSON而不是使用适当的轮询框架是否有任何缺点?

为了举例,我假设我每隔5秒刷新一次处理作业的状态。

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....")