简体   繁体   中英

Dealing with concurrent Ajax requests

I'm trying to do the following:

  • I have a list of links, each performing a different Ajax call when clicked.
  • Each Ajax response is assigned a target where it will be displayed.
  • While a request is being processed, the links can still be clicked (= further Ajax calls).
  • The example below has two targets and four links: two point to DIV#d1, two point to DIV#d2.

How can I make sure that only the response to the last request sent will eventually be displayed in its target DIV ?

If I click on the link labelled Data1 , then Data2 , the first call must be aborted because Response1 could arrive after Response2. The problem seems to imply that I must keep track of previous requests for each target, so I can abort them whenever a new request is made.

I've written this piece of code. I'd like to know if you think this is the approach is right.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title></title>
  </head>
  <body>
    <ul>
      <li><a href="data1.htm" class="trigger" data-target="d1">Data 1</a></li>
      <li><a href="data2.htm" class="trigger" data-target="d1">Data 2</a></li>
      <li><a href="data3.htm" class="trigger" data-target="d2">Data 3</a></li>
      <li><a href="data4.htm" class="trigger" data-target="d2">Data 4</a></li>
    </ul>
    <div id="d1"></div>
    <div id="d2"></div>
    <script type="text/javascript" src="/test/jquery-1.7.1.min.js"></script>
    <script type="text/javascript">
      $(function(){
        var register = {};

        $(".trigger").on("click", function() {
          var target = $(this).attr("data-target");
          var url = $(this).attr("href");
          if (register[target] == undefined) register[target] = [];

          ajaxCall = $.get(url, function(data) { // Ajax request
            $("#" + target).html(data);
          });

          for (a in register[target]) { // Aborts existing ajax requests for this target
            register[target][a].abort();
          }
          register[target] = []; // Empty register for this target
          register[target].push(ajaxCall); // Register current ajax request

          return false;
        });

      });
    </script>
  </body>
</html>

Your idea is right in my view. However, you should not use for in to loop over an array. Also you might want to abort all calls first (just to be sure).

Actually, you're clearing the array each request and only fill it with one ajax call. In this case, it is not necessary to loop over the array, since you know it will only contain one element if the array is not empty. On the other hand, you don't know whether it will contain zero or one element, so a loop is the most concise way to abort a call if it is present.

Also, you can use .data to get data- attributes.

Lastly, you could make use of the || trick.

var target = $(this).data("target"),
    url = $(this).attr("href");

register[target] = register[target] || [];

$.each(register[target], function() {
    this.abort();
});

ajaxCall = $.get(url, function(data) { // Ajax request
    $("#" + target).html(data);
});

register[target].push(ajaxCall); // Register current ajax request

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM