如何在 AngularJS 中编写去抖动服务 [英] How to write a debounce service in AngularJS
问题描述
underscore 库提供了一个 debounce 函数,可以防止在设定的时间段内多次调用一个函数.他们的版本使用了 setTimeout.
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.
我们如何在纯 AngularJS 代码中做到这一点?
How could we do this in pure AngularJS code?
此外,我们是否可以利用 $q 样式的 promise 来在 debounce 周期后从被调用函数中检索返回值?
Moreover, can we make use of $q style promises to retrieve the return value from the called function after the debounce period?
推荐答案
以下是此类服务的工作示例:http://plnkr.co/edit/fJwRER?p=preview.它创建了一个 $q
延迟对象,该对象将在最终调用去抖动函数时解析.
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.
每次调用 debounce
函数时,都会返回对内部函数下一次调用的承诺.
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;
};
};
}]);
您可以通过对 Promise 使用 then 方法从去抖动函数中获取返回值.
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);
});
};
如果您快速连续多次调用 logReturn
,您将看到 logReturn
调用一遍又一遍地记录,但只记录一个 addMsg
调用.
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.
这篇关于如何在 AngularJS 中编写去抖动服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!