简体   繁体   English

在 Angular 中消除 HTTP 请求

[英]Debouncing HTTP requests in Angular

I've built a loading spinner component in Angular 2 that I'd like to trigger before http requests are made and disable when they're done.我已经在 Angular 2 中构建了一个加载微调组件,我想在发出 http 请求之前触发它,并在请求完成后禁用它。 The problem is that each time the user changes an input (checks of of a box, types into the input box), the http request fires.问题是每次用户更改输入(检查框,在输入框中键入)时,都会触发 http 请求。 This means a lot of requests, and the overlay is coming up constantly.这意味着很多请求,并且覆盖层不断出现。 I'd like to wait a set period of time (half a second?) after an input is triggered before triggering the http request, giving the user time to put in other inputs.我想在触发输入之后等待一段时间(半秒?),然后再触发 http 请求,让用户有时间输入其他输入。 I've read up a bit on debounce, but as far as I can see, that's for time waiting before making another request?我已经阅读了一些关于 debounce 的内容,但据我所知,这是在发出另一个请求之前等待的时间? And as far as I can see, that's just a buffer time between requests.据我所知,这只是请求之间的缓冲时间。

Basically, right now, I have a component that handles my inputs.基本上,现在,我有一个组件来处理我的输入。 When an input is changed (checkboxes right now), the following code is triggered:当输入更改时(现在是复选框),将触发以下代码:

@Output() filtersChanged = new EventEmitter();
emitFilters(): void {
    this.filtersChanged.emit(this.filters);
}

Which through an intermediary step, sets off my http request:通过一个中间步骤,触发了我的 http 请求:

getEvents(filters): Observable<Event[]> {
    this.loadingSpinnerService.showLoadingSpinner();
    let params: URLSearchParams = new URLSearchParams();
    params.set('types', filters.types.join(','));
    params.set('dates', filters.dates.join(','));
    return this.http
        .get('//api.dexcon.local/getEvents.php', { search: params })
        .map((response: Response) => {
            return response.json().events;
        });
}

In Angular 1, I would have put it in a timeout which refreshed each time a user affected an input, so it'd trigger a set time after the final input was touched.在 Angular 1 中,我会将其置于每次用户影响输入时刷新的超时中,因此它会在触摸最终输入后​​触发设定的时间。 Is this the best way to do it in Angular 2 as well?这也是在 Angular 2 中做到这一点的最佳方式吗? From my reading, debounce locks out a request from happening too close to a second request, but I'm wondering how to best prevent a request from happening after an action is taken for a given period of time.根据我的阅读,去抖动锁定了一个请求,使其不会发生太接近第二个请求,但我想知道如何最好地防止在给定时间段内采取操作后发生请求。

The easiest way to accomplish what you're after is to set up a Subject (I'm assuming you have access to Rxjs here).完成你所追求的最简单的方法是设置一个主题(我假设你可以在这里访问 Rxjs)。 Initialize one in your component:在您的组件中初始化一个:

inputSubject: Subject<string> = new Subject<string>();

Since a Subject is both an observer and an observable, you're going to want to set up a subscription to listen for changes.由于 Subject 既是观察者又是可观察者,因此您需要设置订阅以监听更改。 Here's where you can apply your debounce.您可以在此处应用去抖动。

this.subscription = this.inputSubject.asObservable()
    .debounceTime(1000)
    .subscribe(x => this.filtersChanged.emit(this.filters));

Now, in your emitFilters() function instead of directly emitting, push the value onto the Subject.现在,在您的 emitFilters() 函数中,而不是直接发射,将值推送到主题上。

this.inputSubject.next(newValue);

Don't forget to store your subscription as a member of your component class and dispose of it properly in your OnDestroy().不要忘记将订阅存储为组件类的成员,并在 OnDestroy() 中正确处理它。

ngOnDestroy() {
    if (this.subscription) {
      this.subscription.unsubscribe();
    }
}

You should be able to solve this by decorating your getEvents method with a debounce function:您应该能够通过使用 debounce 函数装饰 getEvents 方法来解决此问题:

    function debounce(ms: number) {

        let timeoutId;

        return function (target: Object, propName: string, descriptor: TypedPropertyDescriptor<any>) {
            let originalMethod = descriptor.value;
            descriptor.value = function (...args: any[]) {
                if (timeoutId) return;
                timeoutId = window.setTimeout(() => {
                    timeoutId = null;
                }, ms);
                return originalMethod.apply(this, args);
            }
        }
    }

And then simply apply it to your method like this (set the decorator parameter to your desired debounce time in ms):然后像这样简单地将它应用到你的方法中(将装饰器参数设置为你想要的去抖动时间,以毫秒为单位):

@debounce(300)
getEvents(filters): Observable < Event[] > {
    ...
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM