Search code examples
angularangular-httpclientangular-http-interceptors

How to skip outdated responses with angular?


What is a best pattern to cancel outdated requests to server in angular (not angularjs)?

  1. User initiate search request #1
  2. User initiate search request #2
  3. Server returns search response #2
  4. Server returns Search response #1

As result, we are getting bug that request and response in UI do not match.

Typeahead, for instance, has typeahead-wait-ms attribute which partially helps, but I am looking for a more generic solution.

Is there easy pattern to cancel requests? Or compare request id with latest one?

PS: We are using HttpClient so our calls internally looks similar to following implementation for GET:

protected get<T>(url: string, request: any = {}, options: any = {}): Observable<T> {
    request.rnd = (new Date()).getTime();

    return this.http.get<T>(url, {headers: this.buildHeaders(options),
        responseType: 'json', params: request})
    .pipe(
            catchError((err: HttpErrorResponse) => {
                ... error Handlig
            })
        );
}

Solution

  • generally it looks like this, if you're using reactive forms, and your source for the string is a formcontrol:

    searchSource = new FormControl('')
    search(searchString: string) {
      // returns observable of search logic
    }
    ngOnInit() {
      this.searchSource.valueChanges.pipe(
        switchMap(toSearch => this.search(toSearch)) // switchmap automatically cancels old requests on new values
      ).subscribe(results => {
        // always results for LAST emitted value
      })  
    }
    

    the key is using switchMap at the source of your value of interest so that you are only looking at the result of the latest value.