Search code examples
javascriptjqueryajaxchainedpause

Pausing Large number of AJAX calls, multiple data sets


I am trying to create a web utility that take several large datasets and makes ajax calls to process them and index them into a table for searching. Basically, the data will be broken down into 5 data sets, but for the sake of simplicity, I will reduce the sample data to two sets (basically multi-dimensional arrays).

  • Inventory Items
  • Systems

Let's just say, again for the sake of simplicity, that each dataset has 3 items in it.

JAVASCRIPT PART 1

var inventory = [
  {"id": "1","title": "0002\/840","type": "inventory"}, 
  {"id": "2","title": "0002\/841","type": "inventory"}, 
  {"id": "3","title": "0002\/842","type": "inventory"}
];
var systems = [
  {"id": "28","title": "System 1","type": "system"}, 
  {"id": "54","title": "System 2","type": "system"}, 
  {"id": "76","title": "System 3","type": "system"}
];

The way it should work is that the code hits the first inventory item, makes an ajax call based on it, waits for the response , and then moves to the second item. It does this over and over again until it reaches the last item, at which point, it moves on to the next data set (systems), and then works its way through those.

Now, I have this working just fine. You can see a fully functional example at the CodePen link below. This version of the JS code has a small delay built in to better demonstrate the issue.

WORKING EXAMPLE


It has now been requested that I add a pause/unpause function. I'm at a little bit of a loss as to how to stop this without freezing the browser, and more so, how to resume where I left off at the correct place in the correct dataset.

I tried adding a paused boolean variable that is toggled on and off, and then a loop in my function that would just wait for the paused variable to be false. This obviously tied up the browser window.

Can anyone shed some light on how I might be able to go about doing pausing and unpausing without freaking out the browser?

Thanks in advance.


REMAINING JAVASCRIPT PART 2

var paused = false;

function PauseIndexing() {
  //paused = true;
}

function BeginIndexing() {
  updateItems(inventory, 'inventory', 0, function () {
    //This gets called when inventory is done
    updateItems(systems, 'systems', 0, function () { 
      alert("Inventory and Systems Imported");
    });
  });
}

function updateItems(items, type, x, callback) {

  /* This causes complete freeze as expected*/
  //while (paused) {}

  var item_count = items.length;

  $.post('', {
    item: items[x],
    type: type
  }, function () {
    x++;
    if (x == item_count) {
      callback();
    } else {
      updateItems(items, type, x, callback);
    }
  });

}

Solution

  • Here you have to maintain the state of progress using pausedAt = x, then continue from where you left. Below is the changed snippets & the working example link.

    function BeginIndexing(x) {
       updateItems(inventory, 'inventory', x, function () {
         pausedAt = x = 0;
        updateItems(systems, 'systems', x, function () {
          alert("Inventory and Systems Imported");
        });
      });
    }
    function ContinueIndexing(){
      paused = false;
      console.log(pausedAt)
      BeginIndexing(pausedAt);
    } 
    function updateItems(items, type, x, callback) {
    if(paused){
      pausedAt = x;
      return
    }
    

    Working Pen

    or else check the result below

    var paused = false;
    var pausedAt = 0;
    var inventory = [
      {"id": "1","title": "0002\/840","type": "inventory"}, 
      {"id": "2","title": "0002\/841","type": "inventory"}, 
      {"id": "3","title": "0002\/842","type": "inventory"}, 
      {"id": "2","title": "0002\/841","type": "inventory"}, 
      {"id": "3","title": "0002\/842","type": "inventory"}, 
      {"id": "2","title": "0002\/841","type": "inventory"}, 
      {"id": "3","title": "0002\/842","type": "inventory"}, 
      {"id": "2","title": "0002\/841","type": "inventory"}, 
      {"id": "3","title": "0002\/842","type": "inventory"}
    ];
    var systems = [
      {"id": "28","title": "System 1","type": "system"}, 
      {"id": "54","title": "System 2","type": "system"}, 
      {"id": "76","title": "System 3","type": "system"}
    ];
    
    function PauseIndexing() {
      paused = true;
      //pausedAt = x;
    }
    
    function BeginIndexing(x) {
       updateItems(inventory, 'inventory', x, function () {
         pausedAt = x = 0;
        updateItems(systems, 'systems', x, function () {
          alert("Inventory and Systems Imported");
        });
      });
    }
    function ContinueIndexing(){
      paused = false;
      console.log(pausedAt)
      BeginIndexing(pausedAt);
    } 
    function updateItems(items, type, x, callback) {
    if(paused){
      pausedAt = x;
      return
    }
      /* This causes complete freeze as expected*/
      /*
      while (paused) {
    
      }
    	*/
      
      var item_count = items.length;
    
      setTimeout(function(){
        $.post('http://www.geonames.org/countries/', {
          item: items[x],
          type: type
        }, function () {
          x++;
          console.log(x);
          if (x == item_count) {
            updateBar(item_count, 100, type);
            updateText("<span style='color:#090;'>Done!</span>", type);
            callback();
          } else {
            var perc = Math.round((x / item_count) * 100);
            updateBar(x, perc, type);
            updateItems(items, type, x, callback);
          }
    
        });
      }, 500);
    }
    
    function updateText(val, type) {
      $('small.' + type + '_name').html(val);
    }
    
    function updateBar(x, perc, type) {
      $('.progress.' + type + ' .progress-bar')
        .attr('aria-valuenow', perc)
        .css('width', perc + '%')
        .html(x + ' (' + perc + '%)');
    }
    
    function isFunction(functionToCheck) {
      var getType = {};
      return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
    }
    .progress{background:#333;}
    <link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet"/>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <div class="btn btn-lg btn-success" onclick="BeginIndexing(0);">Start!</div>
    
    <div class="btn btn-lg btn-primary" onclick="PauseIndexing(true);">Pause</div>
    <div class="btn btn-lg btn-primary" onclick="ContinueIndexing(false);">Continue</div>
    
    
    
    <div class="panel">
            <div class="panel-body">
                <h2>9 Inventory Items</h2>
                <small class="inventory_name">Pending....</small>
                <div class="progress inventory">
                  <div class="progress-bar progress-bar-striped active" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%">
                    0 (0.00%)
                  </div>
                </div>
            </div>
        </div>
        
        
        <div class="panel">
            <div class="panel-body">
                <h2>3 Systems</h2>
                <small class="systems_name">Pending....</small>
                <div class="progress systems">
                  <div class="progress-bar progress-bar-striped active" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%">
                    0 (0.00%)
                  </div>
                </div>
            </div>
        </div>