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

查看:16
本文介绍了具有相同请求的多个 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 个选项:

There are essentially 2 options:

  1. 是否可以选择使用forkJoin() 将所有的observable组合成一个数组

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

  • 优点:你知道你会在你内部加载所有数据subscribe()
  • 缺点:在 forkJoin 发出值之前,您必须等待 每个 HTTP 请求完成
    • 注意:你可以实现一个很好的辅助函数,比如@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 并在 一个 observables 完成时做出反应

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

      • 优点:您不必等待每个 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 答案 解释了 Observable 清理,以及 这里是一篇相关的 RxJS 文章,内容是关于放置 takeUntil() 的位置.

      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天全站免登陆