0

Does anyone have any pointers for me to debounce the keypress event in angular? I can't get it to debounce. And I know for sure because I'm using $log.debug to print out the keys pressed, and the amount of times it fires off is not at the debounce rate.

I have set it up like this:

<div ng-keypress="doSomething"></div>

and in my controller (not that I have included underscore.js to utilize its debounce method in this instance):

...
$scope.doSomething = function(event, keyEvent) {
    var keypressed = String.fromCharCode(keyEvent.which).toUpperCase();
    _.debounce(handleKeyPress(keypressed), 500);
}

function handleKeyPress(keypressed) {
    //do something with the keypress
}

Thanks for your help in advance.

John Fu
  • 1,812
  • 2
  • 15
  • 20
  • What do you mean by the amount of times it fires off is not at the debounce rate? – Jayram Apr 21 '15 at 03:48
  • 1
    When calling `_.debounce(handleKeyPress(keypressed), 500);` you are resolving `handleKeyPress(keypressed)` and passing the result to be debounced. You should be passing a function that can be called. Something like: `var bounceable = function() {handleKeyPress(keypressed)}` `_.debounce(bounceable, 500);` – Enzey Apr 21 '15 at 03:50
  • Hi Enzey, That made perfect sense. I've applied it, but it doesn't run. I don't get any errors either. I tried putting just a console.log statement inside the debounce function and it doesn't even call that. – John Fu Apr 21 '15 at 04:16

1 Answers1

1

Try the following code:

$scope.doSomething = _.debounce(function(event, keyEvent) {
    $scope.$apply(function() {
    // Do something here
    });
}, 500);

Working Plunker

As @Enzey said, _.debounce() returns a "debounced" function that needs to be called somewhere to have any effect. And you need to call $apply() in order to trigger a digest cycle. Otherwise any changes on the model made within the debounced function won't update the view.

Update

It turned out that what the OP really wanted was a throttled function. Below is another code snippet using _.throttle():

$scope.doSomething = _.throttle(function($event) {
    if ($scope.$$phase) return; // Prevents 'digest already in progress' errors

    $scope.$apply(function() {
        // Do something here
    });
}, 100);
Michael Benford
  • 14,044
  • 3
  • 60
  • 60
  • This is very close. I have played with your plunkr code, and have set the delay to 100ms. If you kept your keypress on a letter for a second, you should get around 10 prints of the same letter. But you don't. Any ideas? – John Fu Apr 21 '15 at 05:39
  • 1
    @JohnFu You seem to be confusing `debounce` with `throttle`. A *debounced* function will only be executed if it's not called again within the specified delay. On the other hand, a *throttled* function will be executed at most once per every X milliseconds. I'll update the plunker to show both. Let me know if that's what you want and I'll update my answer. – Michael Benford Apr 21 '15 at 17:08
  • Many thanks for that. I had no idea and that makes sense. You learn something new everyday. – John Fu Apr 22 '15 at 00:54