web-dev-qa-db-ja.com

Observables:新しいサブスクリプションコールで以前のhttpリクエストをキャンセルする

プロジェクトの検索機能に取り組んでいます。ユーザーが検索バーに何かを入力すると、検索テキストに変更があった場合、検証のためにテキストをバックエンドに送信し、応答(テキストのエラーまたはエラーなし)を受け取ります。

this.searchBar.on('change', () => {

    http.post('api_link', {searchText: 
       this.serachBar.searchText}).subscribe(resp => {
            this.resp = resp['Result'];
       });
    })

ユーザーが検索バーに継続的に入力すると、複数の検証応答がバックエンドから受信されます。ただし、新しい変更では最新のサブスクリプションのみが有効であり、以前のAPIの呼び出しは無意味です。

Subscribeを使用して、apiへの新しい呼び出しで以前のサブスクリプションをキャンセルできる方法はありますか?

注:すべての応答を待つだけで済むように思えるかもしれませんが、検索バーの下に応答も表示します(それまではローダーを表示します)。したがって、さまざまな応答状態の間で遷移するのではなく、最新の応答が利用可能になるまでローダーにロードを続けてもらいたいのです。

7
V_S_X

私はすべてを反応性に保つためにサブジェクトを使用します。テンプレートhtmlで変更イベントをリッスンし、新しい値をサブジェクトに送信します。

_ <searchBar (change)="search$.next($event.target.value)" />
_

次に、コンポーネントで:

_  this.subscription = this.search$.pipe(
     debounceTime(800), 
     distinctUntilChanged(),
     switchMap(searchText=>http.post('api_link', {searchText})
    }).subscribe(response=>{
       this.response = response.
    });
_

サブジェクトを通じて新しい値が発行された場合、switchMapは完了していないHTMLリクエストをキャンセルします。 debouneTimeで遊んで、自分に合ったものを確認できます。最後に、ngOnDestroyでサブジェクトのサブスクライブを解除してください。これにより、メモリリンクが防止され、すべてが適切に実行されます。

_ngOnDestroy(){
   this.subscription. unsubscribe();
}
_

Sureshの answer には、ソリューションへの優れた追加機能であるdistinctUntilChanged()があります。私はそれを追加していますが、彼の答えを以下に挙げたいと思います。 Eggを検索するとリクエストが行われるため、これは利点です。しかし、私はEggの最後にsを追加し、デバウンスが完了する前に考えを変えて、Eggの検索を含む別の重複HTTP投稿が作成されないようにします。

2
JoshSommer

DebounceTimeおよびswitchMap演算子を使用する必要があります。

this.searchBar.on('change', () => {

    of(this.serachBar.searchText).pipe(
       debounceTime(400),
       distinctUntilChanged(),
       switchMap((text)=> {
          return http.post('api_link', {searchText: text}).map(resp => {
            return resp['Result'];
          });
        });
    ).subscribe(response=> console.log(response));

});
0