RxJs switchMap与角度HttpClient

时间:2018-02-28 18:17:29

标签: angular rxjs observable angular-httpclient switchmap

每当触发新请求时,我都会有一个用例,应该取消/忽略任何已经在飞行中的http请求。

例如

  
      
  • 当请求#1花费太长时间来响应/减慢网络连接时,请求(比如#2)进入。
  •   
  • 在这种情况下,#2从服务器获得非常快速的响应,然后在任何时候,即使#1回复了HTTP响应的响应   应该忽略可观察性。
  •   
  • 我面临的问题是,首先,组件显示来自请求#2的响应值,并在req#1完成时再次更新(这不应该发生)。
  •   

我认为switchMap取消obervables /维持发出可观察值的顺序。

摘自我的服务。

Obervable.of('myServiceUrl')
             .switchMap(url => this.httpRequest(url) )
              .subscribe( response => {
                   // implementation
                   /** Update an observable with the 
                       with latest changes from response. this will be 
                       displayed in a component as async */
                });


private httpRequest(url) {
        return this.httpClient.get('myUrl', { observe: 'response' });
}

以上实施不起作用。有人可以找出这个用例的正确实现。

2 个答案:

答案 0 :(得分:3)

您似乎正在创建多个可观察对象。从您的示例中不清楚,但似乎每次要发出请求时都会调用Observable.of。这样每次都会创建一个 new Observable流,因此对于每个后续调用,您将获得一个新流,而前一个流不会被取消。这就是.switchMap无效的原因。

如果您希望.switchMap取消HTTP请求,则需要它们使用相同的可观察流。您要使用的源Observable取决于触发http请求的确切内容,但您可以使用Subject之类的内容自行管理。

const makeRequest$ = new Subject();
const myResponse$ = makeRequest$.pipe(switchMap(() => this.service.getStuff()));

您可以订阅myResponse$以获得回复。只要您想触发请求,就可以执行makeRequest$.next()

答案 1 :(得分:0)

我有以下代码摘录,switchMap实现是成功的。

class MyClass {
    private domain: string;
    private myServiceUri: subject;
    myData$: Observable<any>;

        constructor(private http: HttpClient) {
            .....
            this.myServiceUri = new Subject();
            this.myServiceUri.switchMap(uri => {
                    return this.http.get(uri , { observe: 'response' })
                            // we have to catch the error else the observable sequence will complete
                            .catch(error => {
                                // handle error scenario
                                return Obervable.empty(); //need this to continue the stream
                            });
                    })
                    .subscribe(response => {
                        this.myData$.next(response);
                    });
        }

        getData(uri: string) {
            this.myServiceUri.next(this.domain + uri); // this will trigger the request     
        }

    }