Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
481 views
in Technique[技术] by (71.8m points)

javascript - Ajax too slow - Recursion

A ajax code that i am using to request a page is consuming too much memory and is making the browser slow and everything lag. It seems like there is recursion going on and i dont know of any way to prevent it. Here is what the code looks like.

$(".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();
});

How can i solve this problem? Thanks in advance.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You are recursing and you shouldn't be using this form of nested setInterval. Doing this, will cause an explosion of interval instances. Instead of using setInterval, schedule additional requests using setTimeout.

setInterval will fire and continue firing every interval until you tell it to stop.

setTimeout will fire once.


Let's consider the following code which should address some of the issues you are having in this question as well as your other 2 questions.

First off, as we said before, don't use setInterval unless you actually want it to run forever. Additionally, don't nest the setInterval creations unless you actually mean to.

Instead, let's create a recursive function getTimeLeft() that will handle firing the request and scheduling the next check for time left after some duration.

This example also mocks the $.ajax() function so that you can see the function in action since we don't have an actual back end to use.

// 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>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...