Ajax太慢 - 递归

时间:2018-06-05 17:28:05

标签: javascript ajax performance recursion

我用来请求页面的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();
});

我该如何解决这个问题?提前谢谢。

1 个答案:

答案 0 :(得分:0)

正在递归,你不应该使用这种形式的嵌套setInterval。这样做会导致间隔实例爆炸。不使用setInterval,而是使用setTimeout安排其他请求。

setInterval将开始并继续射击每个间隔,直到你告诉它停止。

setTimeout会触发一次。

让我们考虑以下代码,这些代码可以解决您在此问题中遇到的一些问题以及其他2个问题。

首先,正如我们之前所说的那样,除非你真的希望它永远运行,否则不要使用setInterval。此外,除非您真正想要,否则不要嵌套 setInterval作品。

相反,让我们创建一个递归函数getTimeLeft(),它将处理触发请求并安排下一次检查一段时间后剩余的时间。

此示例还嘲笑$.ajax()函数,以便您可以看到该函数正在运行,因为我们没有实际的后端可供使用。

&#13;
&#13;
// 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));
&#13;
<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>
&#13;
&#13;
&#13;

此代码将解决您在2 Ajax non-blocking中遇到的问题,因为每个元素都有自己的逻辑,可以提取和获取剩余时间并自行更新。

这也解决了您在Timer in Ajax - Preemption中可能遇到的问题,因为现在该元素不会检查以确定在上一次检查完成之前还剩多少时间。