【问题标题】:how to use switchMap to cancel pending http requests and taking the last subscribe only?如何使用 switchMap 取消挂起的 http 请求并只接受最后一次订阅?
【发布时间】:2023-03-19 00:01:02
【问题描述】:

我尝试使用 subscription.unsubsribe 取消挂起的 http 请求,如下所示:

getAgentList(pageNumber: number, filter: string): any {
   let requestUrl: string = 'api/service/agents_search?ACCT=' 
   +this.accountId;

if ( this.subscription ) {
    this.subscription.unsubscribe();
}

this.subscription =  this.backEndCommService.getData(requestUrl)
.subscribe(
        (res: any) => {
        let serverResponse: ServerResponse = new 
        ServerResponse(this.accountId, pageNumber, res.search_results, 
        res.resultRows, res.pageSize, res.resultPages)
                this._agentListData.next(serverResponse);
            },   
       (err: HttpErrorResponse) => {
                let errorMessage: string;
                if (err instanceof TypeError) {
                    errorMessage = 'Script error: ' + err.message;
                } 
                console.log(errorMessage);
    });
}

我想知道如何将 switchMap 应用到此代码以终止对 URL 的挂起请求(例如,当第一次搜索花费很长时间并且输入第二个并且我想关闭第一个时,自动完成搜索输入。) 谢谢

【问题讨论】:

    标签: angular rxjs httprequest observable switchmap


    【解决方案1】:

    基本示例:

    export class MyComponent{
        private $filter: Subject<string> = new Subject<String>();
    
        constructor(){
            this.$filter
              .switchMap(filter => this.backEndCommService.getData(filter + this.baseUrl)
              .subscribe(res => {//do something})
        }
    
        getAgentList(filterValue: string){
            this.$filter.next(filterValue);
        }
    
    }
    

    要使用 switchmap 来取消先前的请求,我们需要一个热的 observable 来输出我们的过滤器值。我们为此使用了一个主题。每次我们从某个地方得到一个新值?我们把它推到主题上。

    【讨论】:

    • 感谢您的回答,这听起来很有希望,但是当我尝试它时,对服务器的调用甚至没有发出,它默默地掉下来,没有任何错误......请看代码:
    • 1.你订阅了吗? 2. 订阅后有没有给next打电话?
    • 这个解释帮助我解决了一个 http 取消问题。我没有意识到 switchMap 取消了之前的订阅。
    • 你还在ne ngOnDestroy吗?
    • 是的,你几乎总是需要取消订阅一个热门的 observable。
    【解决方案2】:

    试过了,连服务器都没有出来

    getAgentList(pageNumber: number, filter: string): any {
        let requestUrl: string = 'api/service/agents_search?ACCT=' 
      +this.accountId;
        if (filter) {
            requestUrl = requestUrl + '&filter=' + filter;
        }
        if (pageNumber) {
            requestUrl = requestUrl + '&pageNumber=' + pageNumber;
        }
        this.$filter.next(requestUrl)
    
        this.$filter.switchMap(requestUrl => 
        this.backEndCommService.getData(requestUrl))
                .subscribe(
                    (res: any) => {
                        let serverResponse: ServerResponse = new 
                        ServerResponse(this.accountId, pageNumber, 
                        res.search_results, 
                        res.resultRows, res.pageSize, res.resultPages)
                        this._agentListData$.next(serverResponse);
                    },
                   (err: HttpErrorResponse) => {
    
                console.log('handling error');
          });
    }
    

    这一行 switchMap(requestUrl => this.backEndCommService.getData(requestUrl)) 没有拨打电话并且 静静地坠落.....mmmm

    【讨论】:

    • 这没什么意义。
    • 你应该忽略变量名的含义。让我们忽略代码...我想编写一个 getdata 函数,它将创建 url 并访问服务器,如果它挂起并且我收到新请求,则挂起将被取消。我如何做到这一点?谢谢。
    【解决方案3】:

    看起来问题是subscriptionnext 之后完成。把它想象成 DOM 上的addEventListener。添加侦听器(在本例中为订阅者)后,您会收到事件。

    getAgentList(pageNumber: number, filter: string): any {
        let requestUrl: string = ‘...’
    
        // assuming this.$filter is a Subject
        // subscription to it first
        this.$filter.switchMap(requestUrl => this.backEndCommService.getData(requestUrl))
            .subscribe(
                (res: any) => {
                    let serverResponse: ServerResponse = new 
                    ServerResponse(this.accountId, pageNumber, 
                    res.search_results, 
                    res.resultRows, res.pageSize, res.resultPages)
                    this._agentListData$.next(serverResponse);
                },
               (err: HttpErrorResponse) => {
                    console.log('handling error')
               }
        );
    
        // then call next()
        this.$filter.next(requestUrl)
    }
    

    大概就是这样。除非,this.$filter 是 BehaviorSubject 或 ReplaySubject,否则我们可能会遇到不同的问题。

    【讨论】:

    • 刚刚注意到@robindijkhof 指出了这一点,但也许完整地看到它会让它更加明显
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多