【问题标题】:RxJs switchMap with angular HttpClient带有角度 HttpClient 的 RxJs switchMap
【发布时间】:2018-02-28 18:17:29
【问题描述】:

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

例如

  • 一个请求(比如 #2)进来了,而请求 #1 响应时间过长/网络连接速度慢。
  • 在这种情况下,#2 会在任何时候从服务器获得非常快速的响应,即使 #1 返回 HTTP 响应的响应也是如此 observable 应该被忽略。
  • 我面临的问题是,首先组件显示来自请求 #2 的响应值,并在请求 #1 完成时再次更新(这不应该发生)。

我认为 switchMap 取消了 obervables / 维护了 observable 值的发出顺序。

摘自我的 service.ts

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' });
}

上述实现不起作用。有人能找出这个用例的正确实现吗?

【问题讨论】:

  • 你是如何使用httpResponse$的?
  • 我不需要 httpResponse$,因为所有的实现都在 subscribe() 中进行了处理。更新了代码 sn-p。

标签: angular rxjs observable angular-httpclient switchmap


【解决方案1】:

您似乎正在创建多个可观察对象。从您的示例中不清楚,但似乎您每次想要提出请求时都致电Observable.of。这每次都会创建一个 new Observable 流,因此对于每个后续调用,您都会获得一个新流,并且不会取消前一个流。这就是.switchMap 不起作用的原因。

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

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

您可以订阅myResponse$ 以获取回复。任何时候想要触发请求,都可以makeRequest$.next()

【讨论】:

  • 这是有道理的。因此,通过上述实现,makeRequest$ 保存了我使用的实际 http get 请求。我对吗 ?让我执行并返回。
  • makeRequest$ 只是一个没有真正做任何事情的主题(可观察)。您只需向它发射以使可观察流发射。 myResponse$ 会有你想要的 http 响应。
  • 我在使用上述方法时遇到错误,即 TypeError: this.myServiceUri.pipe.switchMap is not a function。此外,当我使用此 vscode 时,会显示 `import { switchMap} from 'rxjs/operators';` 未使用。
【解决方案2】:

下面是 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     
        }

    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-10-12
    • 2020-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多