Использование setInterval() для упрощенного непрерывного опроса
Для простого веб-приложения, которому нужно обновлять части данных, представляемых пользователю через заданные интервалы, есть ли недостатки в использовании setInterval() для получения JSON из конечной точки вместо использования надлежащей структуры опроса?
Для примера, скажем, я обновляю статус задания обработки каждые 5 секунд.
Ответы
Ответ 1
Из моего комментария:
Я бы использовал 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);
Ответ 2
Простая неблокирующая функция опроса может быть реализована в последних браузерах с использованием 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)
Ответ 3
Вы можете сделать так:
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);
Ответ 4
Я знаю, что это старый вопрос, но я наткнулся на него, и в способе StackOverflow делать то, что я думал, я мог бы его улучшить. Возможно, вы захотите рассмотреть решение, подобное тому, что описано здесь, которое известно как длительный опрос. Или другое решение - это WebSockets (одна из лучших реализаций веб-сокетов с основной целью работы во всех браузерах) socket.io.
Первое решение в основном суммируется, когда вы отправляете один запрос AJAX и ожидаете ответа перед отправкой дополнительного, а затем, как только ответ был доставлен, поставите в очередь следующий запрос.
Между тем, на бэкэнд вы не возвращаете ответ, пока не изменится статус. Таким образом, в вашем сценарии вы использовали бы цикл while, который будет продолжаться до тех пор, пока статус не изменится, а затем верните измененный статус на страницу. Мне действительно нравится это решение. Как видно из приведенного выше ответа, это то, что делает facebook (или, по крайней мере, в прошлом).
socket.io - это, в основном, jQuery для Websockets, так что любой браузер, в котором находятся ваши пользователи, может установить соединение сокета, которое может выводить данные на страницу (без опроса вообще). Это ближе к мгновенным уведомлениям Blackberry, которые - если вы собираетесь на мгновение, это лучшее решение.
Ответ 5
Просто измените @bschlueter 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....")