I am trying to debounce an AJAX call to only send it once, but unfortunately, it tells me that what I am passing it is not a function. Here is my code:
getItems: function(page){
this.page = page;
console.log(typeof(this.getBackendItems));
_.debounce(this.getBackendItems(page), 500);
},
getBackendItems: function(page){
this.$http.get("{{url('api/user/items')}}", {page : page}).success(function(response){
this.items = response.data;
this.last_page = response.last_page;
});
},
Console.log says that getBackendItems is a function and still an error is thrown that not a function is passed to _.debounce() call.
There are several things wrong with this:
When you are trying to pass the function like this: this.getBackendItems(page)
you are running it, so _.debounce
does not receive the function, but the result of the function, which in this case, is a Promise object.
this.getBackendItems
passes the functionthis.getBackendItems(page)
runs the function, and passed the resultBut then, how do you tell it which arguments to use?
Well, _.debounce()
returns your original function, but wrapped with the debounce logic. So you cache it in a variable and execute that function with your desired arguments (page
). So the syntactically correct Way to use debounce would be more like this:
getItems: function(page){
this.page = page;
console.log(typeof(this.getBackendItems));
var debouncedFunction = _.debounce(this.getBackendItems.bind(this), 500); // properly bind the function so "this" is the vue component.
debouncedFunction(page)
},
But, that too won't work, because getItems
itself is not debounced, so all this code will do is create many, many debounced functions, which will all fire once the 500ms is kicking in. Not a good idea.
Now my question is: how do you invoke this function? from a v-on:click? Then Vue got you covered:
<a v-on:click="getItems(page) | debounce 500">Some Link</a>
With that filter, you don't need to use _.debounce
at all.
If you call this function some other way, let me know.
Edit: update due to comment feedback:
<a href="#"
@click.prevent="getItems(page) | debounce 500"
@click="pageBuffer = pageBuffer +1">
Click Me
</a>
JS:
var App = new Vue({
el: '#app',
data() {
return {
page: 1,
pageBuffer: 0
}
},
methods: {
getItems: function(page) {
this.getBackendItems(page + this.pageBuffer)
this.pageBuffer = 0
}
}
})