可观察对象:取消新订阅呼叫上的先前的HTTP请求

时间:2018-11-22 13:30:11

标签: angular rxjs httprequest observable subscribe

我正在为我的项目开发搜索功能。用户在搜索栏上键入任何内容后;对于搜索文字的任何更改,我都会将其发送到后端进行验证并收到响应(文字中有错误或没有错误):

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

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

现在,当用户不断在搜索栏中键入内容时,后端会收到多个验证响应。但是,在进行任何新更改时,只有最新的订阅才有效,并且以前对api的任何调用都是无效的。

有什么方法可以使用订阅取消对api的任何新调用的先前订阅吗?

注意:似乎可以等待所有响应,但是我还将在搜索栏下方显示响应(直到那时显示一个加载程序)。因此,我希望加载程序一直加载直到最新的响应可用,而不是在各种响应状态之间转换。

2 个答案:

答案 0 :(得分:3)

我会使用一个主题来使所有内容保持反应性。在您的模板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,则会发出请求。但是随后我在蛋的末尾添加了s,并在去抖完成之前改变了主意。将不会再进行另一个重复的HTTP帖子,搜索蛋。

答案 1 :(得分:0)

您需要使用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));

});
相关问题