【问题标题】:How to synchronize http.get requests in Angular, when the second request depends on the first one?当第二个请求依赖于第一个请求时,如何在 Angular 中同步 http.get 请求?
【发布时间】:2019-07-19 00:48:27
【问题描述】:

我需要从 Angular 对我的数据库执行一系列 http 请求。在第一步中,我得到一个对象数组。这工作正常。 在第二步中,我想用附加数据填充每个对象。所以我需要等待第一个 http.request 完成。 我也不想在我的数据被提取之前返回。

我的函数 getData() 应该返回一个 Observable,因为接口/签名不应该改变(因为它正在程序的其他部分使用,并且 observable 对程序逻辑有意义)。

// Returns an array with objects, that have an id, that is needed for the second call 

data[] : Object = new Array(); 
populatedData[] : Object = new Array();


getData(): Observable<Object[]>{
  this.http.get<Object[]>("http://localhost:3000/data").subscribe(data => this.data = data);

// This needs the data from the first call 
 for(int i = 0; i < data.length; i++){
this.http.get<Object>("http://localhost:3000/data/"+data[i].id).subscribe(data => populatedData.push(data)); 
}


return of(populatedData); 

}

【问题讨论】:

    标签: javascript angular typescript


    【解决方案1】:

    您可以使用switchMap(在初始 GET 完成后,发出其他请求)和forkJoin(发出多个请求并在所有请求完成后发出)。像这样的:

        getSingleEntry = ({ id }) => this.http.get<Object[]>("http://localhost:3000/data/" + id);
    
        getData = () => this.http.get<Object[]>("http://localhost:3000/data")
            .pipe(
                tap(data => this.data = data),
                switchMap(data => forkJoin(data.map(this.getSingleEntry)));
    
    

    【讨论】:

      【解决方案2】:

      承诺是一种选择,但另一种选择也可以,

      // Returns an array with objects, that have an id, that is needed for the second call 
         data[] : Object = new Array(); 
         populatedData[] : Object = new Array();
      
        getData(): Observable<Object[]>{
           this.http.get<Object[]>("http://localhost:3000/data").subscribe((data)=>{
            this.data = data;
                   for(int i = 0; i < data.length; i++){
                        this.http.get<Object>("http://localhost:3000/data/"+data[i].id).subscribe((response)=> {
                                populatedData.push(response)
                         }); 
                   }
               });
            return of(populatedData); 
          }
      

      【讨论】:

        【解决方案3】:

        您应该将需要第一次调用的代码放在第二次调用中

        data: Array<any> = []; 
        populatedData: Array<any> = []; 
        
        
        
        getData(): Observable<Object[]> {
            this.http.get<Object[]>('http://localhost:3000/data').subscribe(data => {
                this.data = data;
                for (let i = 0; i < data.length; i++) {
                    this.http
                        .get<Object>('http://localhost:3000/data/' + data[i].id)
                        .subscribe(data => populatedData.push(data));
                }
            });
        
            return of(populatedData);
        }
        

        【讨论】:

        • 异步函数的返回类型必须是Promise。
        • getData 正在返回的 observable 甚至在第一个请求完成之前就已解决,更不用说最后一个了。
        • 没有。它应该在请求完成后发出,而不是在发送前发出。 getData 的订阅者将立即收到一个空数组。
        【解决方案4】:

        我认为最好的办法是使用switchMap RXJS 运算符和zip。在第二次调用中,您可以访问第一次调用的数据。然后你可以在所有调用完成后返回值数组。

        有关switchMap 的更多信息,您可以阅读here。关于ziphere

        这里有示例数据看起来像https://rxviz.com/v/Mogdv96O

        那么你的代码将被重构如下:

          getData(): Observable<Object[]> {
            this.http.get<Object[]>("http://localhost:3000/data")
              .pipe(switchMap((data) =>
                      zip(...data.map(item => this.http.get<Object>("http://localhost:3000/data/" + item.id)))
                    )
              );
          }
        

        【讨论】:

          猜你喜欢
          • 2023-03-31
          • 1970-01-01
          • 1970-01-01
          • 2021-01-04
          • 2019-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-06-05
          • 1970-01-01
          相关资源
          最近更新 更多