具有相同请求的多个API调用 [英] Multiple API calls with same request

查看:64
本文介绍了具有相同请求的多个API调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用相同的端点通过不同的ID进行多个HTTP调用.有没有更好的方法可以从UI处理此问题.我们现在无法更改后端,有更好的方法吗?

I want to make multiple HTTP calls with the same endpoint passing different id. Is there a better way to handle this from UI. We cannot change the backend right now, is there a better way?

import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, forkJoin } from 'rxjs';

@Component({
  selector: 'app-root',
  templateUrl: 'app/app.component.html'
})
export class AppComponent {
  loadedCharacter: {};
  constructor(private http: HttpClient) {}

  ngOnInit() {
    let character1 = this.http.get('https://swapi.co/api/people/1');
    let character2 = this.http.get('http://swapi.co/api/people/2');

    forkJoin([character, character2]).subscribe(results => {
      // results[0] is our character
      // results[1] is our character2
    });
  }
}

推荐答案

基本上有2个选项:

  1. 您是否可以使用 forkJoin() 将所有可观察对象组合成一个数组

  1. Is the option you have where you use forkJoin() to combine all the observables into an array

  • PROS :您知道您将在 subscribe()
  • 中加载所有数据
  • 缺点:,您必须等待每个 HTTP请求完成,然后 forkJoin 发出该值
    • 注意:您可以实现一个不错的帮助程序功能,例如@Prince建议
    • PROS: you know you will have all your data loaded inside you subscribe()
    • CONS: you have to wait for every HTTP request to finish before forkJoin emits the value
      • Note: you can implement a nice helper function like @Prince recommended

      您可以使用 mergeMap() 您的ID并在一个可观察对象完成时做出反应

      You can use mergeMap() for your IDs and react whenever one of the observables completes

      • PROS :您不必等待每个 HTTP请求完成.您可以在完成后对它们进行反应.此外,您可以更轻松地处理错误(因此,如果一个请求失败,您仍然可以继续处理其他请求).
      • 缺点:,您必须稍微不同地处理 .subscribe()中的发射值
      • PROS: you don't have to wait for every HTTP request to complete. You can react as they complete. Also, you can handle errors easier (so if one request fails you can still continue with the other requests).
      • CONS: you have to handle your emitted values in the .subscribe() a little differently

      最终,您将需要确定哪种方法最适合您.您的实现没有任何问题.我注意到您将 loadedCharacter 保留为对象,因此,老实说,选项2可能对您的用例有用

      At the end of the day, you will need to decided which approach is best for you. There isn't anything wrong with the implementation you have. I noticed you are keeping your loadedCharacter as an object, so honestly option 2 may be good for your use case

      选项2 的示例代码.参见 stackblitz 以获得一个小型演示:

      Example code for Option 2. See this stackblitz for a small demo:

      import { Component } from '@angular/core';
      import { HttpClient } from '@angular/common/http';
      import { Observable, from, Subject } from 'rxjs';
      import { mergeMap, takeUntil } from 'rxjs/operators';
      
      @Component({
        selector: 'app-root',
        templateUrl: 'app/app.component.html'
      })
      export class AppComponent {
        private endSubs$ = new Subject();
        loadedCharacter: {};
        constructor(private http: HttpClient) {}
      
        ngOnInit() {
          /* ids of all the characters you want to load*/
          const characterIds = [1, 2];
      
          /* this will emit each id as a value */
          from(characterIds).pipe(
      
            /* merge each id to an Observable of the http get request */
            mergeMap(id => this.http.get(`https://swapi.co/api/people/${id}`)),
      
            /* cancel any pending requests when the component unloads.
              this will avoid any RxJS memory leaks */
            takeUntil(this.endSubs$)
          ).subscribe(
            character => {
              /* note that you will only receive 1 character at a time */
              console.log('received character', character);
              this.loadedCharacter[character.id] = character; // or whatever you want to do
            },
            err => console.log('Error loading a character', err),
            () => console.log('All character requests have finished')
          );
        }
      
        /* clean up our subscriptions when the component destroys */
        ngOnDestory() {
          this.endSubs$.next();
          this.endSubs$.complete();
        }
      }
      

      编辑:我添加了一些RxJS清理代码,以避免 mergeMap 引起的任何内存泄漏.卸载此组件时,任何待处理的请求都将被取消.此处是一个示例SO答案,解释了可观察的清理,并

      I added some RxJS cleanup code to avoid any memory leaks from the mergeMap. Any requests that are pending when this component unloads will be cancelled. Here is an example SO answer explaining Observable cleanup, and here is a relevant RxJS article on where to place your takeUntil().

      这篇关于具有相同请求的多个API调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆