I\'m implementing a simple infinite-scroll directive in Angular2.
I\'m using @HostListener(\'window:scroll\')
to get the scroll event and parsing the data from
I really like @yurzui's solution and I updated a lot of code to use it. However, I think it contains a bug. In the original code, there is only one timeout
per class but in practice one is needed per instance.
In Angular terms, this means that if the component in which @debounce()
is used is instantiated multiple times in a container, every instantiation will cancelTimeout
the previous instantiation and only the last will fire.
I propose this slight variant to eliminate this trouble:
export function debounce(delay: number = 300): MethodDecorator {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const original = descriptor.value;
const key = `__timeout__${propertyKey}`;
descriptor.value = function (...args) {
clearTimeout(this[key]);
this[key] = setTimeout(() => original.apply(this, args), delay);
};
return descriptor;
};
}
Of course, it is possible to be more sophisticated about disambiguating the synthetic __timeout__
property.
I would leverage debounce method decorator like:
export function debounce(delay: number = 300): MethodDecorator {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const timeoutKey = Symbol();
const original = descriptor.value;
descriptor.value = function (...args) {
clearTimeout(this[timeoutKey]);
this[timeoutKey] = setTimeout(() => original.apply(this, args), delay);
};
return descriptor;
};
}
and use it as follows:
@HostListener('window:scroll', ['$event'])
@debounce()
scroll(event) {
...
}
Ng-run Example