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
213 views
in Technique[技术] by (71.8m points)

How to write a debounce service in AngularJS

The underscore library provides a debounce function that prevents multiple calls to a function within a set period of time. Their version makes use of setTimeout.

How could we do this in pure AngularJS code?

Moreover, can we make use of $q style promises to retrieve the return value from the called function after the debounce period?

See Question&Answers more detail:os

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

1 Answer

0 votes
by (71.8m points)

Here is a working example of such a service: http://plnkr.co/edit/fJwRER?p=preview. It creates a $q deferred object that will be resolved when the debounced function is finally called.

Each time the debounce function is called the promise to the next call of the inner function is returned.

// Create an AngularJS service called debounce
app.factory('debounce', ['$timeout','$q', function($timeout, $q) {
  // The service is actually this function, which we call with the func
  // that should be debounced and how long to wait in between calls
  return function debounce(func, wait, immediate) {
    var timeout;
    // Create a deferred object that will be resolved when we need to
    // actually call the func
    var deferred = $q.defer();
    return function() {
      var context = this, args = arguments;
      var later = function() {
        timeout = null;
        if(!immediate) {
          deferred.resolve(func.apply(context, args));
          deferred = $q.defer();
        }
      };
      var callNow = immediate && !timeout;
      if ( timeout ) {
        $timeout.cancel(timeout);
      }
      timeout = $timeout(later, wait);
      if (callNow) {
        deferred.resolve(func.apply(context,args));
        deferred = $q.defer();
      }
      return deferred.promise;
    };
  };
}]);

You get the return value from the debounced function by using the then method on the promise.

$scope.addMsg = function(msg) {
    console.log('addMsg called with', msg);
    return msg;
};

$scope.addMsgDebounced = debounce($scope.addMsg, 2000, false);

$scope.logReturn = function(msg) {
    console.log('logReturn called with', msg);
    var promise = $scope.addMsgDebounced(msg);
    promise.then(function(msg) {
        console.log('Promise resolved with', msg);
    });
};

If you call logReturn multiple times in quick succession you will see the logReturn call logged over and over but only one addMsg call logged.


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

...