Search as you type in Angular to display accurate results when the server doesn't return data in the order it's requested?
<p>So I'm building a website for a client. On our search page, I'm watching the search bar and every key stroke fires a new search request so it will update the results as you're typing. My issue is when I type in a search term really fast the server can 'hickup' and doesn't return my results in the order I requested them. This causes only some pieces of my markup which are bound to the returning data to display the wrong values. For example. If I type in the word "video". 99% of the time I get the correct results and all of my labels look correct. 1% of the time however, my search for "vide" will return after my search for the "video" which causes it to display the wrong results and the wrong total. Unfortunately I can't link a live demo due to a non disclosure agreement but I can post the code that makes this run. We're in the late stages of production so it's more important to get it functioning correctly asap, than it is to use best practice.
Some pieces of the html:</p>

<pre><code>&lt;h1&gt;Search&lt;/h1&gt;
                &lt;p ng-cloak class="results-message fade-in"&gt;
                  &lt;span ng-if="items.loaded &amp;amp;&amp;amp; term"&gt;{{total}} results for "{{term}}"  &lt;/span&gt;        
                  &lt;span ng-if="!total &amp;amp;&amp;amp; !term"&gt;No query was entered &lt;/span&gt;
                  &lt;span ng-if="!items.loaded &amp;amp;&amp;amp; term"&gt;Searching...&lt;/span&gt;
                &lt;/p&gt;
                &lt;div class="search-container"&gt;         
                    &lt;input type="search" name="term" value="asd" ng-init="term='asd'" ng-model="term" placeholder="Enter your search term" ng-keydown="$event.keyCode == 13 ? $event.preventDefault() : 0;" class="search"&gt;
                    &lt;input type="image" name="submit" src="/_res/astoncarter/img/images/search-icon.gif" alt="Submit"&gt;
                &lt;/div&gt;
            &lt;/div&gt;

&lt;ul ng-cloak ng-class="{loading: loading}" class="results"&gt;
               &lt;li ng-if="items.loaded &amp;&amp; !items.length &amp;&amp; term" class="fade-in"&gt;
                    &lt;h2&gt;No results were found for {{term}}&lt;/h2&gt;
                &lt;/li&gt;
                &lt;li ng-if="!term" class="fade-in"&gt;
                    &lt;p class="text-center"&gt;Please enter a search query&lt;/p&gt;
                &lt;/li&gt;
                &lt;li ng-repeat="item in items" class="fade-in"&gt;
                    &lt;h2&gt;&lt;a href="{{item.url}}"&gt;{{item.title}}&lt;/a&gt;&lt;/h2&gt;
                    &lt;p&gt;{{item.teaser}}&lt;/p&gt;
                &lt;/li&gt;
            &lt;/ul&gt;
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;
&lt;p ng-if="count == 10" class="load-more"&gt;&lt;a href="" ng-if="!loading" ng-click="loadQuery()" class="btn"&gt;Load More&lt;/a&gt;&lt;a href="" ng-if="loading" disabled class="btn"&gt;&lt;i class="fa fa-spinner fa-spin"&gt; &lt;/i&gt; LOAD&lt;/a&gt;&lt;/p&gt;
</code></pre>

<p>The JS:</p>

<pre><code>app.controller('ListingCtrl', function ($scope, $element, $timeout, acAPIservice, $location, $interval) {
  // Grabbing and using the attribute from the dom is not the Angular way 
  // but a compromize if we want BE developers to be able to set the API
  // Other options would be to set a global variable to be output and used
  $scope.apiUrl = $element.attr('data-api-url');
  $scope.pageSize = $element.attr('data-page-size');
  $scope.language = $element.attr('data-language');
  $scope.timer = 3; 

  $scope.term = undefined;
  $scope.items = [];
  $scope.start = 0;
  $scope.end = 0;
  $scope.total = 0;
  $scope.loading = false;


 // main worker to get data
 // lists that need data should call this on ng-init
 $scope.loadQuery = function(){
   $scope.loading = true;

  var payload = {
    pageSize : $scope.pageSize,
    start : $scope.end+1,
    language : $scope.language
  };
  if($scope.term) {
    payload.term = $scope.term
  }

  acAPIservice.getSearch($scope.apiUrl, payload) //this just hits a factory with the url and payload and returns the data object
  .success(function (data) {
    $scope.timer = 3; //reset the timer
    $scope.items = $scope.items.concat(data.results);
    $scope.start = data.start;
    $scope.end = data.end;
    $scope.total = data.total;
    $scope.loading = false;
    $scope.items.loaded = true;
    $scope.count = data.count;
  })
  .error(function(data, status, headers, config){      
    $scope.items = [];
    $scope.items.loaded = true;
  });
};

// cheating a bit here. We let the ng-init attribute for term trigger 
// the first batch. Also grabs new batches when term is updated
$scope.$watch('term', function(newValue, oldValue) {
// reset everything
$scope.items = [];
$scope.start = 0;
$scope.end = 0;
$scope.total = 0;
// if we still have a search term go get it
if($scope.term){
  $scope.loadQuery();

  //because you can't turn off async in angular we need to set a timer that gets reset every time you load a query.     After 1 second we recall to make sure our total reflects the accurate num
  var promise = $interval( function(){ 
      $scope.timer = $scope.timer-1;
      if($scope.timer === 0){ //if the timer runs out it means that no terms have been entered in 1 second, which we will then cancel the interval and and do one last load
        $interval.cancel(promise);
        $scope.loadQuery();
      }
  }, 500);
}
  });
});
</code></pre>

<p>It always displays the correct search term, however it will display the {{total}} from whichever is returned last and it seems like the results from the last 2 returns are being appended together. </p>

<p>I just tried implementing the interval to sort of "refresh" the results after a second has passed without the user typing, but sometimes the server can take longer than 1 second, which means it will still update with the wrong info. Please ask me any questions if you need me to clear something up. I have a hard time explaining my issues sometimes. Also sorry for the formatting:(</p>