javascript - Ajax 太慢 - 递归
问题描述
我用来请求页面的 ajax 代码消耗了太多内存,使浏览器变慢并且一切都滞后。似乎有递归正在进行,我不知道有什么方法可以防止它。这是代码的样子。
$(".item").each(function() {
$this = $(this);
var dataString = {s: "<?echo $_SESSION['currentview_'.$stamp]?>", r:"<?echo $search_usernumber?>", st: "<?echo $stamp?>"};
$.ajaxSetup({cache:false});
function timeLeft() {
$.ajax({
type: "POST",
url: "get_content_home.php",
dataType: "html",
data: dataString,
success: function(result) {
$this.html(result);
//console.log("a");
window.setInterval(function() {
timeLeft();
}, 500);
}
});
}
timeLeft();
});
我怎么解决这个问题?提前致谢。
解决方案
你是递归的,你不应该使用这种形式的 nested setInterval
。这样做会导致间隔实例的爆炸式增长。不要使用setInterval
,而是使用 来安排其他请求setTimeout
。
setInterval
将触发并在每个间隔继续触发,直到您告诉它停止。
setTimeout
会开火一次。
让我们考虑以下代码,它应该解决您在这个问题中遇到的一些问题以及您的其他 2 个问题。
setInterval
首先,正如我们之前所说,除非您真的希望它永远运行,否则不要使用。此外,除非您真的打算这样做,否则不要嵌套创作。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 中的 Timer - Preemption中可能面临的问题,因为现在元素不会再次检查以查看还剩多少时间,直到上一次检查完成之后。
推荐阅读
- amazon-web-services - 无法在 AWS 上编辑权限 JSON,尽管它告诉我我可以
- cartopy - 无法使用 cartopy 显示经纬度和海岸线
- django - 将主页和关于页面添加到 Django 动态 sitemap.xml
- python - 如果它在字符串中并导致错误,则返回错误消息 - Python 3
- php - 在 Laravel 8 中使用 $errors 变量包含额外的验证
- java - Maven - 从多模型项目中构建几个模块
- shell - 为 Redis 实例定制的 liveness probe
- regex - 如何设置正则表达式部分的最大长度?
- javascript - 仅在需要时在 vue 中显示加载元素
- javascript - 如何安全地接受包含来自 WYSIWYG 编辑器的 iframe 的用户输入?