I have a Method call (server-side) that queries an external API on keyup, not the best in terms of performance and I’m hitting the API pretty hard. Is there some way to throttle the method call? Essentially waiting with the request until a certain delay has passed after the last keystroke.
I’d probably do it something like this:
Template.something.onCreated(function() {
this.debounce = null;
});
Template.something.events({
'keyup input#some-id': function() {
var instance = Template.instance();
if (instance.debounce) {
Meteor.clearTimeout(instance.debounce);
}
instance.debounce = Meteor.setTimeout(function() {
Meteor.call(...);
}, 200);
}
});
Great, thanks!
@robfallows is right, you’ll want to debounce your function… Since underscore is part of core though you might as well use underscores debounce function
Template.something.events({
'keyup input#some-id': _.debounce(function() {
//code here
}, 200);
});
edit: fix typo => _debounce
That is much more compact .
However, you should add the underscore package to your app if you use this (even though it’s currently in the core).
I have debounce as package too and using it this way, which way is the best from compatibility point of view?
Template.searchForm.events({
"keyup #searchStreamer": _.debounce(function (event, template) {
RunSearch({searchStreamer: event.target.value, searchSkip: 0});
},1000)
...
use _debounce, or _.debounce or how?
that’s great. thank you
Hey everyone! I know this is an older thread, sorry to bump it out from the grave, but I recently encountered an issue related to this topic and thought I’d share my experience in case it might help someone else.
If you are using _.debounce(
directly in the template event as suggested in a previous post:
Template.searchForm.events({
"keyup #searchStreamer": _.debounce(function (event, template) {
RunSearch({searchStreamer: event.target.value, searchSkip: 0});
},1000)
...
When you reuse this template multiple times in your app, different instances of the template will share a single instance of the event callbacks. This could cause some input events to be missed, as they get ‘debounced’ by other input events.
In my case, I had a form with multiple input fields, each being an instance of the template. The template had a debounced event handler, which saved the new input value to the database using a method call. If a user entered data into the form really quickly across multiple input fields, only the last input would be recorded on the server, because the debounce timer was being reset by the latest input event.
To resolve this issue, I created an instance of the debounced method call on the template instance and called it from the event handler
Like so:
Template.searchForm.onCreated(function(){
template.debouncedSearchStreamer = _.debounce(function(searchStreamer, searchSkip) {
RunSearch({searchStreamer, searchSkip});
},1000);
});
Template.searchForm.events({
"keyup #searchStreamer": function (event, template) {
teamplate.debouncedSearchStreamer(event.target.value, 0);
}
...
While this specific example with a search input might not be the best (since there’s likely only one search box), it was a helpful solution for my form with multiple instances of input field templates. There also may be a better, easier solution to this issue as well.
I hope this helps someone else facing a similar issue with reusable templates and debouncing.