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

时间:2017-08-23 15:56:44

标签: angular http rxjs

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

      <div class="row"> 
        <div>
          {{#data1 }}
           <div id="AboutUsDiv1" >
              <h3 class="Title">{{Title}}</h3>
              <p class="text">  {{Text}}</p>                      
            </div>
           {{/data1 }}
         </div>
       </div>

    <hr>

    <div class="row">       
         <div>
          {{#data2}}
            <div id="AboutUsDiv2" >
               <h3 class="Title">{{Title}}</h3>
               <p class="text">{{Text}}</p>                       
            </div>
           {{/data2}}
          </div>
    </div>

但是,如果我将var contentUpdate = require("./functions/ContentUpdate"); ... app.get('/aboutUs', function(req,res){ contentUpdate.showAboutUs1; contentUpdate.showAboutUs2; }); 替换为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();

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

5 个答案:

答案 0 :(得分: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);
    });
}

答案 1 :(得分:8)

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

我使用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被订阅。您可以通过短语切换到新的可观察对象来记住这一点。

答案 2 :(得分:6)

对我来说问题是因为一个空的可观察者。 我在可观察列表中使用了Observable.forkJoin

解决方案:我需要为Observable.of()提供一个值:Observable.of(null)

答案 3 :(得分:0)

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

Observable.of(null)

答案 4 :(得分:0)

我发现路由有时会取消所有请求。例如,我路由到 /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);
});

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