【问题标题】:Send multiple asynchronous HTTP GET requests发送多个异步 HTTP GET 请求
【发布时间】:2017-01-12 17:22:05
【问题描述】:

我需要多次调用 API,因为 API 不支持对多个项目的请求。到目前为止,我所写的内容最终陷入了向服务器发送 GET 请求的无限循环中。我相信我不理解以下示例中 Observables 的性质。我的假设是,while 循环中的每个调用都订阅一个新的单个对象,并且当它被解析时,它将被放置在数组中。如何修改下面的代码来实现我想要的?

getSingle(): Observable<Single> {
    return this.http.get(this.url, this.options)
     .map((r: Response) => r.json().data as Single);
}

getMultiple(num: number): Single[] {
    let multiple: Single[] = [];

    let i = 0;
    while (i < num) {
        this.getSingle().subscribe(single => {
            multiple.push(single);
            console.log('Success');
            i++;
        }, err => {
            console.log('Failure');
        });
   }

   return multiple;
}

【问题讨论】:

    标签: angular typescript observable


    【解决方案1】:

    应避免使用while 循环发出多个异步HTTP 请求,然后分别订阅所有这些请求,以免打开许多Observable 连接。我们可以改用Observable.forkJoin 运算符。

    这就是实现的样子:

    getSingle(singleUrl: string): Observable<Single> {
        return this.http.get(singleUrl, this.options)
            .map((r: Response) => r.json().data as Single);
    };
    
    getMultiple(): Observable<Array<Single>> {
        let singleUrls = ['singleUrl1', 'singleUrl2', 'singleUrl3']; // can be replaced with any 'Single' identifier
    
        let singleObservables = singleUrls.map((singleUrl: string, urlIndex: number) => {
            return this.getSingle(singleUrl)
                .map(single => single as Single)
                .catch((error: any) => {
                    console.error('Error loading Single, singleUrl: ' + singleUrl, 'Error: ', error);
                    return Observable.of(null); // In case error occurs, we need to return Observable, so the stream can continue
                });
        });
    
        return Observable.forkJoin(singleObservables);
    };
    
    this.getMultiple().subscribe(
        (singles: Array<Single>) => {
            console.log(singles); // [Single, Single, Single];
            // In case error occured e.g. for the 'singleUrl' (our 'Single' identifier) at position 1,
            // Output wil be: [Single, null, Single];
        }
    );
    

    希望这会有所帮助!

    【讨论】:

    • 考虑使用 mergeDelayError 而不是 forkJoin 和“hackish” catch:它的好处是它不会将结果压缩到一个数组中,当所有请求都完成后,你会获得适当的error 回调,以防万一。
    【解决方案2】:

    理想情况下,您只需在构造函数中订阅一次,因为订阅块可以被多次调用,然后在循环中使用 RxJS 主题和 next()

    但是,如果您不太在意,一个快速解决方法是:

    this.getSingle().first().subscribe
    

    您将需要导入第一个运算符。这将确保只调用一次订阅。这样你就可以分多次,不用担心。

    我猜你收到无限 HTTP 请求的原因是你的失败块被击中,你需要做......

    }, err => {
           i++;
            console.log('Failure');
     });
    

    【讨论】:

      猜你喜欢
      • 2023-03-06
      • 2011-01-08
      • 2015-06-09
      • 2016-09-04
      • 2018-04-10
      • 1970-01-01
      • 2013-06-01
      • 1970-01-01
      • 2022-07-26
      相关资源
      最近更新 更多