How to write a debounce service in AngularJS

前端 未结 7 710
说谎
说谎 2020-11-27 11:01

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.

H

7条回答
  •  爱一瞬间的悲伤
    2020-11-27 11:37

    Pete BD gave a good start to the debounce service, however, I see two problems:

    1. returns when you should send in a work() callback that uses javascript closure if you need to change state in the caller.
    2. timeout variable - isn't that timeout variable a problem? timeout[] maybe? imagine 2 directives using debounce - signalr, input form validator, I believe the factory approach would break down.

    What I am currently using:

    I changed factory to a service so each directive gets a NEW instance of debounce aka new instance of the timeout variable. - i haven't ran into a situation where 1 directive will need timeout to be timeout[].

    .service('reactService', ['$timeout', '$q', function ($timeout, $q) {
        this.Debounce = function () {
            var timeout;
    
            this.Invoke = function (func, wait, immediate) {
                var context = this, args = arguments;
                var later = function () {
                    timeout = null;
                    if (!immediate) {
                        func.apply(context, args);
                    }
                };
                var callNow = immediate && !timeout;
                if (timeout) {
                    $timeout.cancel(timeout);
                }
                timeout = $timeout(later, wait);
                if (callNow) {
                    func.apply(context, args);
                }
            };
            return this;
        }
    }]);
    

    in my angularjs remote validator

        .directive('remoteValidator', ['$http', 'reactService', function ($http, reactService) {
            return {
                require: 'ngModel',
                link: function (scope, elm, attrs, ctrl) {
                    var newDebounce = new reactService.Debounce();
    
                    var work = function(){
    //....
                    };
    
                    elm.on('blur keyup change', function () {
                       newDebounce.Invoke(function(){ scope.$apply(work); }, 1000, false);
                    });
                }
            };
        }])
    

提交回复
热议问题