【问题标题】:Angular 4. A series of http requests get cancelledAngular 4.一系列http请求被取消
【发布时间】:2017-08-23 15:56:43
【问题描述】:

当我尝试通过 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

但如果我像上面那样将.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();

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

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

我为什么会遇到这种行为?我需要理解,而不是绕过。我如何在不进行合并、分叉等的情况下提出一系列请求?

【问题讨论】:

  • 我可以绕过,在这种情况下,谢谢!

标签: angular http rxjs


【解决方案1】:

这与 observable 被取消有关,尽管我必须承认我不知道您所面临问题的根本原因。

我在使用 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));
                            }
                            ));

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

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

switchMap 与其他扁平化操作符的主要区别在于取消效果。在每次发射时,先前的内部 observable(您提供的函数的结果)被取消并订阅新的 observable。您可以通过短语 switch to a new observable 记住这一点。

【讨论】:

  • 我今天遇到了这个问题,现在我已经阅读了你的回复,我觉得使用 switchMap 很愚蠢,然后想知道为什么事情会被取消。我想我会尝试使用mergeMap!非常感谢您的回答。
  • @JasonB 感谢 mergeMap 提示。这为我解决了问题。
  • 刚刚在 Angular v9 中遇到了同样的问题。切换到 mergeMap 解决了这个问题。感谢您的提示!
【解决方案2】:

对我来说,问题是因为一个空的 observable。 我在 observables 列表中使用了Observable.forkJoin

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

【讨论】:

  • 类似的解决方案——我的 forkJoin 中列出的每个 observables 都需要 .pipe(catchError(() => of(null)));
【解决方案3】:

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

感谢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);
    });
}

【讨论】:

  • 现在我感觉很糟糕,因为我打算对此发表评论,但只是假设您的示例被简化了。如果您需要在没有订阅的情况下执行 http 请求。您可以调用http.get(...).take(1),它将在获取第一个项目后订阅并销毁订阅。
  • @ctTag 是否 take(1) 会在没有订阅方法的情况下调用请求事件?
  • @ctTag 不,不会。马上查了。但我刚刚意识到,对于 http 方法,使用 .take(1) 非常合乎逻辑
  • 这似乎是通过使用 HttpClient (Angular 4.3+) 解决的
  • 我在 Angular 6.1.9 的 HttpClient 中遇到了完全相同的问题,我通过从 switchMap 到 mergeMap 的交换解决了这个问题。谢谢!
【解决方案4】:

我发现路由有时会取消所有请求。例如,我路由到 /home 但想在前面添加一个键,所以我路由到 /fred/home。 Chrome 在它的智慧中取消了待处理的任务。留下一个半负载的系统。

使用路由器重定向后我不得不延迟 10 毫秒

 this.router.navigate([event.value, 'home']);
// We have to wait for the actual navigation to complete or else chrome will cancel API calls.
timer(10).subscribe(() => {
  this.spaceSelectionService.setSpace(event.value);
});

当然在幕后设置空间会加载各种配置。那个小小的停顿解决了我的问题。

【讨论】:

  • 您是否可能正在使用一些自动取消订阅工具,例如github.com/ngneat/until-destroy?他们将取消您的请求(与取消任何 observable 的方式相同)
  • 这是内置于 chrome 本身的。我手动编写我的代码直到代码。
【解决方案5】:

就我而言,这与他们的回答中提到的@Kevin Upton 和@Mahesh 有关。我也在使用 Switch 映射的 observables 列表中使用 Forkjoin。但其中一个在某个时候返回未定义。我不必将 Switch 地图更改为合并地图。对我来说,ForkJoin 需要所有可观察对象都需要返回一些东西,至少:

Observable.of(null)

【讨论】:

    【解决方案6】:

    HTTP 请求被取消的原因可能有多种。我多次遇到同样的问题,所以提一些可以帮助解决问题的方法。

    1. 如果一个组件在 HTTP API 调用完成之前被销毁(例如 - 假设我们在模态中调用一个 HTTP API,并且如果我们在 HTTP 调用完成之前关闭模态组件)
    2. 在使用 fork-join(或类似类型的运算符)时,如果一个 HTTP 调用失败,那么其他 HTTP 调用将被取消。
    3. 如果 HTTP API 调用太快,那么 chrome 会发现它是可疑的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-10-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-18
      • 2018-03-30
      • 1970-01-01
      相关资源
      最近更新 更多