Вы рекурсивны , и вам не следует использовать эту вложенную форму setInterval
.Это приведет к взрыву интервальных экземпляров.Вместо использования setInterval
, запланируйте дополнительные запросы, используя setTimeout
.
setInterval
будет срабатывать и продолжать стрельбу каждый интервал, пока вы не скажете ему остановиться.
setTimeout
сработает один раз.
Давайте рассмотрим следующий код, который должен решить некоторые из проблем, которые возникают у вас в этом вопросе, а также 2 других вопроса.
Во-первых, как мы уже говорили, не используйте setInterval
, если вы действительно не хотите, чтобы он работал вечно.Кроме того, не nest setInterval
создания, если вы на самом деле не хотите.
Вместо этого давайте создадим рекурсивную функцию getTimeLeft()
, которая будет обрабатывать запрос и планировать следующую проверку.на время, оставшееся после некоторой продолжительности.
В этом примере также выполняется имитация функции $.ajax()
, чтобы вы могли увидеть функцию в действии, поскольку у нас нет фактического внутреннего интерфейса для использования.
// Fake server side data to keep track of time lefts
const timeLefts = {
foo: 0,
bar: 0,
fizz: 0,
buzz: 0
};
const timeLeftsUpdateInterval = setInterval(() => {
for (const [key, val] of Object.entries(timeLefts)) {
timeLefts[key] = Math.min(val + Math.random() * 10, 100);
}
if (Object.entries(timeLefts).every(([k, v]) => v >= 100)) {
clearInterval(timeLeftsUpdateInterval);
}
}, 1000);
// Mock $.ajax function to stub sending AJAX requests
function $ajax(kwargs) {
return {
done: cb => {
setTimeout(() => {
cb(timeLefts[kwargs.data.x]);
}, 500);
}
};
}
// We will check for an update every second after the last request finishes
const timeLeftCheckInterval = 1000;
// Continuously check to see how much time is left for an element
function getTimeLeft(el) {
// Make our request data
const dataString = {
s: "<?echo $_SESSION['currentview_'.$stamp]?>",
r: "<?echo $search_usernumber?>",
st: "<?echo $stamp?>",
// My custom property to make this work
x: el.dataset.item
};
// Make our request to get the time left
const req = $ajax({ // Using our mock $.ajax
type: "POST",
url: "get_content_home.php",
dataType: "html",
data: dataString
});
// Once the request has finished
req.done(data => {
// Set the time left to the element
el.innerHTML = data;
// Have some condition so that you don't check for time left forever
// Eventually there will be no time left right? Why keep checking?
if (data.timeleft <= 0) return;
// Schedule another round of checking for time left after some duration
setTimeout(() => {
getTimeLeft(el);
}, timeLeftCheckInterval);
});
}
// Kick off getting timeleft for all .items
Array.from(document.querySelectorAll(".item"))
.forEach(el => getTimeLeft(el));
<ul>
<li class="item" data-item="foo"></li>
<li class="item" data-item="bar"></li>
<li class="item" data-item="fizz"></li>
<li class="item" data-item="buzz"></li>
</ul>
Этот код решит проблему, с которой вы столкнулись в 2 неблокирующем Ajax , потому что каждый элемент будет иметь свою собственную логику переходаи выбор оставшегося времени и самообновление.
Это также решает проблему, с которой вы можете столкнуться в Таймер в Ajax - Preemption , потому что теперь элемент не будет проверять, сколько времениснова до окончания предыдущей проверки.