Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I have an angular reactive form that makes a simple GET request. If for example, I should get some sort of HTTP error. The observable todo$ has now completed I can no longer change my search options and click to retry searching. I've made a stackblitz demo, in the demo I've added my subscription inside an initializer and if there is an error on the stream I catch it. After I catch it, I call the initializer again. This works but seems like the wrong way to handle errors.

I've set up the form so that I can cancel previous HTTP requests.

export class AppComponent implements OnDestroy {
  todos;
  loading = false;
  useFakeURL = false;
  todoSub$: Subscription;
  todo$: BehaviorSubject < string > = new BehaviorSubject < string > ('');

  @ViewChild('searchInput') searchInput: ElementRef;

  constructor(private provider: ExampleService) {
    this.init();
  }

  ngOnDestroy() {
    this.todoSub$.unsubscribe();
  }

  search() {
    const value = this.searchInput.nativeElement.value;
    this.todo$.next(value);
    this.useFakeURL = !this.useFakeURL;
  }

  private init(): void {
    this.todoSub$ = this.todo$.pipe(
        filter(val => !!val),
        tap(() => {
          this.loading = true;
        }),
        switchMap(() => this.provider.query(this.todo$.getValue(), this.useFakeURL)),
        catchError(error => {
          this.todo$.next('');
          this.init();
          return of([]);
        }),
      )
      .subscribe(
        todos => {
          this.loading = false;
          this.todos = todos;
        },
        err => {
          this.loading = false;
          this.todos = err;
        }
      );
  }
}

export class ExampleService {

  constructor(private http: HttpClient) {}

  query(todo, useFakeURL: boolean) {
    if (todo === 'all') {
      todo = '';
    }
    const url = useFakeURL ? 'poop' : `https://jsonplaceholder.typicode.com/todos/${todo}`;
    return this.http.get(url);
  }
}
<div class="container">
  <input #searchInput type="text" placeholder="Enter a number or enter 'all' to get all todos">
  <button (click)="search()">Get Todos</button>
</div>
<ul *ngIf="!loading && todos && todos.length">
  <li *ngFor="let todo of todos">
    <pre>
      {{todo | json}}
    </pre>
  </li>
</ul>
<pre *ngIf="!loading && todos && !todos.length">
  {{todos | json}}
</pre>
<div *ngIf="loading" class="loader">... LOADING</div>
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
285 views
Welcome To Ask or Share your Answers For Others

1 Answer

Angular's Http requests are immutable. Observable returned from client execute actual call when you subscribe to it. As many times you subscribe as many requests will be made. That is so called "Cold Observable"

If you need to change request, you need a brand new observable from HttpClient.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...