Angular 4.一系列http请求被取消

ego*_*hin 16 http rxjs angular

当我尝试通过Angular 4中的http服务发出多个http请求时,之前的请求会在Chrome中被取消(但它们会到达服务器).例:

const obs1 = this.http.get(`${API_URL}/transitions`);
const obs2 = this.http.get(`${API_URL}/states`);
obs1.subscribe();  
obs2.subscribe(); // this will cancel obs1's http request
Run Code Online (Sandbox Code Playgroud)

但如果我更换.subscribe().publish().connect()上面的,它将正常工作(没有取消)

const obs1 = this.http.get(`${API_URL}/transitions`);
const obs2 = this.http.get(`${API_URL}/states`);
obs1.publish().connect();
obs2.publish().connect();
Run Code Online (Sandbox Code Playgroud)

或者,如果我将两个合并Observables为一个然后像上面那样订阅,它也将正常工作

const obs1 = this.http.get(`${API_URL}/transitions`);
const obs2 = this.http.get(`${API_URL}/states`);
Observable.merge(obs1, obs2).subscribe()
Run Code Online (Sandbox Code Playgroud)

为什么我会面对这种行为?我需要了解,而不是绕过.如何在合并,分叉等的情况下进行一系列请求?

ego*_*hin 10

我发现了这种行为的潜在原因.

感谢https://github.com/ghetolayhttps://github.com/dklmuc

我们发现angular会取消非常快速的http请求,而不需要任何回调.所以,你必须在订阅中传递onNext

来自https://github.com/ghetolay:

好吧,我认为这是竞争条件

它总是会在拆解时调用xhr.abort()

如果浏览器仍认为连接已打开,它将关闭它,否则可能什么都不做

所以当你对响应进行非常快速的处理时(比如没有回调真的非常快),它可能会中止仍然被认为是开放的连接

这个工作正常:

for (let i = 1; i < 50; i++) {
    http.get(`https://swapi.co/api/people/${i}`).subscribe((result) => {
        console.log(i, result);
    });
}
Run Code Online (Sandbox Code Playgroud)

  • 现在我感觉很糟糕,因为我打算对此发表评论,但只是假设您的示例已简化。如果您需要在没有订阅的情况下执行 http 请求。您可以调用`http.get(...).take(1)`,它会在获取第一个项目后订阅和销毁订阅。 (2认同)

Mah*_*esh 10

这与被观察者被取消有关,虽然我必须承认我不知道你面临的问题的根本原因.

我使用ngrx/effects模块遇到了类似的问题.操作处理程序使用ngrx开关映射运算符向服务发出请求.除最后一个请求外的所有请求都将被取消 将其更改为合并映射修复了问题.下面是代码

@Effect()
    loadSomeData$: Observable<Action> = this.actions$
            .ofType(SomeActions.Load_Data)
            .mergeMap((id) =>
                    this.someService.getSomething(id)
                            .map((someEntity) => new SomeActions.LoadDataSuccess(someEntity)
                            ).catch((x, y) => {
                                    console.error('Error occured');
                                    return Observable.of(new SomeActions.LoadDataFailed(id));
                            }
                            ));
Run Code Online (Sandbox Code Playgroud)

在这里复制ngrx的相关部分.

https://www.learnrxjs.io/operators/transformation/switchmap.html

switchMap与其他展平运算符的主要区别在于取消效果.在每次发射时,前一个内部observable(您提供的函数的结果)被取消,并且新的observable被订阅.您可以通过短语切换到新的可观察对象来记住这一点.

  • 今天,我遇到了这个问题,现在,我已经阅读了您的回复,使用switchMap感到很愚蠢,然后想知道为什么事情会被取消。我想我会尝试使用mergeMap!非常感谢您的回答。 (2认同)

Kev*_*ton 7

对我而言,问题是由于可观察到的空白。我使用Observable.forkJoin的是可观察物清单。

解决方案:我需要给我Observable.of()一个价值:Observable.of(null)