Чтобы отменить ожидающий HTTP-запрос и снова вызвать fromEvent в Angular 6 и Rxjs 6 - PullRequest
2 голосов
/ 08 июля 2019

Я могу отменить ожидающий HTTP-запрос (используя .unsubscribe), но после этого он не вызовет мой fromEvent (this.searchInput.nativeElement, 'keyup').Как мне справиться с этим?

Я использую "fromEvent (this.searchInput.nativeElement, 'keyup')" для получения результатов поиска.Но если есть ожидающий запрос HTTP, и пользователь очищает поле, я хочу отменить запрос (я попытался отписаться, и это работает).Но после этого «fromEvent» не сработает.Есть идеи, как с этим справиться?

fromEvent(this.searchInput.nativeElement, 'keyup')
            .pipe(
                map((event: any) => {
                    if (event.keyCode === 17 || event.keyCode === 91 || event.keyCode === 37 || event.keyCode === 38 || event.keyCode === 39 || event.keyCode === 40 || event.keyCode === 13 || event.keyCode === 27) {
                        return;
                    }
                    return event.target.value;
                }),
                filter((query: any) => {
                    if (query === '') {
                        this.loading = false;
                        this.searchedResult = [];
                    }
                    return query && query.length > 0;
                }),
                debounceTime(300)
                ,distinctUntilChanged((p, c) => {
                    return !!this.searchedResult && this.searchedResult.length > 0 && (p == c);
                })
                , switchMap(query => {
                    query = query.trim();
                    this.loading = true;
                    return this.cartService.searchItemByName(encodeURIComponent(query), this.shopID.shop_id.toString()).pipe(
                        catchError(err => {
                            this.toaster.error(err.error.message || "Something went wrong!");
                            return of([]); //in case of error let’s emit an empty array
                        })
                    );
                })
            ).subscribe((res: any) => {
            let data = res.result;
            this.loading = false;
            this.searchedResult = data;
            if (data && data.length) this.setSelectedItem(data[0], 0)
        })

Ответы [ 2 ]

1 голос
/ 08 июля 2019

SwitchMap уже отменяет подписку, если появляется новый поисковый запрос.Так что я бы убрал побочные эффекты из вашего кода и обработал пустой термин case не с помощью фильтра, а с условным возвратом.

fromEvent(document.getElementById('source'), 'keyup')
    .pipe(
        map((event: any) => event.target.value),
        debounceTime(300),
        switchMap(query => {
            const trimmed = query.trim();
            this.loading = true;
            return trimmed === '' ? of([]) : fakeHttp(query);
        })
    )
    .subscribe((res: any) => {
        this.loading = false;
        console.log(res);
    });

В действии: https://stackblitz.com/edit/rxjs-tg4gew?devtoolsheight=60

1 голос
/ 08 июля 2019

takeUntil может сделать работу здесь:

searchInputEvent = new Subject();

fromEvent(this.searchInput.nativeElement, 'keyup')
            .pipe(
                tap(() => this.searchInputEvent.next()),
                map((event: any) => {
                    if (event.keyCode === 17 || event.keyCode === 91 || event.keyCode === 37 || event.keyCode === 38 || event.keyCode === 39 || event.keyCode === 40 || event.keyCode === 13 || event.keyCode === 27) {
                        return;
                    }
                    return event.target.value;
                }),
                filter((query: any) => {
                    if (query === '') {
                        this.loading = false;
                        this.searchedResult = [];
                    }
                    return query && query.length > 0;
                }),
                debounceTime(300)
                ,distinctUntilChanged((p, c) => {
                    return !!this.searchedResult && this.searchedResult.length > 0 && (p == c);
                })
                , switchMap(query => {
                    query = query.trim();
                    this.loading = true;
                    return this.cartService.searchItemByName(encodeURIComponent(query), this.shopID.shop_id.toString()).pipe(
                        takeUntil(this.searchInputEvent),
                        catchError(err => {
                            this.toaster.error(err.error.message || "Something went wrong!");
                            return of([]); //in case of error let’s emit an empty array
                        })
                    );
                })
            ).subscribe((res: any) => {
            let data = res.result;
            this.loading = false;
            this.searchedResult = data;
            if (data && data.length) this.setSelectedItem(data[0], 0)
        })

Он отменит подписку на ранее подписанных searchItemByName наблюдаемых для каждого типа, вызываемого событием keyup. Вы можете считать, что запрос должен быть отменен, как только пользователь наберет номер, или только по истечении времени отката. В этом случае поместите tap после debounceTime

...