Отмените запрос API api в angular 8 при входе в функцию - PullRequest
0 голосов
/ 01 апреля 2020

Я немного застрял. у меня есть форма с вводом имени пользователя, которая должна быть уникальной. поэтому я привязываю к этому входу класс, который запускает вызов сервера и проверяет состояние ввода (используется или не используется). я завернул все с тайм-аутом (чтобы позволить пользователю писать письма, а затем запустить запрос).

код:

static serverUniqueUserNameExists(authService: AuthService, timeout = 1500): AsyncValidatorFn {
    return (control: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null> => {
        return new Observable((observer: Observer<ValidationErrors | null>) => {
            if (control.value.length == 0) {
                observer.next(null)
                observer.complete()
            } else {
                const clearTimer = setTimeout(async () => {
                    const res = await this.getUserNameStatus(authService, control)
                    if (res.status >= '400') {
                        observer.next({ error: true, serverError: true })
                    } else {
                        if (res.data.userExists) {
                            observer.next({ error: true, userNameAlreadyExist: true })
                        } else {
                            observer.next(null)
                            clearTimeout(clearTimer)
                        }
                    }
                    observer.complete()
                }, timeout)
            }
        })
    }
}

но когда я смотрю в сети, я вижу это для каждого письма я набираю, я запускаю запрос к серверу.

мне нужно каким-то образом отменить все предыдущие вызовы API, которые уже были выполнены, и запустить только последний запрос.

не могу найти способ для этого.

кто-то поможет?

1 Ответ

0 голосов
/ 01 апреля 2020

Вы можете создать простое состояние isFetching, которое будет возвращаться всякий раз, когда выполняется запрос. Рекомендую сделать на стороне страницы. Время выборки: добавьте denounce в текстовый ввод, чтобы оно не обновлялось с каждым символом.

let isFetching = false
static serverUniqueUserNameExists(authService: AuthService, timeout = 1500): AsyncValidatorFn {
    return (control: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null> => {
        if(isFetching) return Promise.resolve(null); // return from here
        return new Observable((observer: Observer<ValidationErrors | null>) => {
            if (control.value.length == 0) {
                observer.next(null)
                observer.complete()
            } else {
                const clearTimer = setTimeout(async () => {
                    /// code here
                    isFetching = false;
                    observer.complete()
                }, timeout)
            }
        })
    }
}

// Образец отладки:

results$: Observable
    subject = new Subject()
    constructor(private httpClient: HttpClient) {}
    ngOnInit() {
        this.results$ = this.subject.pipe(
            debounce(() => Rx.Observable.interval(1000)),
            map(searchText => this.httpClient.get("/api/search?q=" + searchText))
        )
    }

Еще: https://blog.bitsrc.io/3-ways-to-debounce-http-requests-in-angular-c407eb165ada

...