Angular 中多个 HTTP 请求的最佳方式

我正在尝试一一发送 2 个 HTTP 请求;如果第一个请求成功,则发送第二个请求,如果没有成功,则显示与第一个请求相应的错误消息。


我计划使用类似的东西,但不确定它是否是这种情况的最佳选择:


import { Component } from '@angular/core';

import { HttpClient } from '@angular/common/http';


@Component({

  selector: 'app-root',

  templateUrl: 'app/app.component.html'

})

export class AppComponent {

  loadedCharacter: {};

  constructor(private http: HttpClient) {}


  ngOnInit() {

    this.http.get('/api/people/1').subscribe(character => {

      this.http.get(character.homeworld).subscribe(homeworld => {

        character.homeworld = homeworld;

        this.loadedCharacter = character;

      });

    });

  }

}

我有不同的请求,例如 PUT 和 CREATE 也使用这种方法。我知道还有其他方法,例如forkjoin,,mergemap但如果这个方法解决了我的问题似乎更具可读性。任何想法?


德玛西亚99
浏览 158回答 4
4回答

料青山看我应如是

首先,你的代码可以工作,这很好——你可以保持原样,一切都会好起来的。另一方面,有一种多重改进的方法将在未来帮助您和您的同事:尝试将与 http 相关的逻辑移至服务中,而不是在组件中调用 http - 这将帮助您将代码拆分为与视图相关的逻辑和与业务/获取/转换相关的逻辑。尽量避免嵌套subscribes - 您不仅会忽略Observables 的强大功能,而且还会将代码绑定到某个流程,而无法在应用程序中的某个地方重用这些行。返回Observable可能会帮助您“共享”请求的结果或以某种方式对其进行转换。flatMap/mergeMap,concatMap并switchMap以不同的方式工作,使您能够按照自己想要的方式控制行为。不过,由于http.get()它们的工作原理几乎相似,因此最好尽快开始学习那些组合运算符。考虑一下在这种情况下您将如何处理错误 - 如果您的第一次调用将导致错误,会发生什么?Observable有一个强大的机制来处理它们,同时.subscribe允许您仅以一种方式处理错误。使用的示例switchMap:import { Component } from '@angular/core';import { HttpClient } from '@angular/common/http';@Component({  selector: 'app-root',  templateUrl: 'app/app.component.html'})export class AppComponent {  loadedCharacter: {};  constructor(private http: HttpClient) {}  ngOnInit() {    const character$ = this.http.get('/api/people/1').pipe(      tap(character => this.characterWithoutHomeworld = character), // setting some "in-between" variable      switchMap(character => {        return this.http.get(character.homeworld).pipe(            map(homeworld => {                    return {                        ...character,                        homeworld: homeworld                    }                }            )        )      }),      catchError(errorForFirstOrSecondCall => {        console.error('An error occurred: ', errorForFirstOrSecondCall);        // if you want to handle this error and return some empty data use:        // return of({});                // otherwise:         throw new Error('Error: ' + errorForFirstOrSecondCall.message);      }));    // you can either store this variable as `this.character$` or immediately subscribe to it like:    character$.subscribe(loadedCharacter => {        this.loadedCharacter = loadedCharacter;    }, errorForFirstOrSecondCall => {       console.error('An error occurred: ', errorForFirstOrSecondCall);    })  }}

蝴蝶不菲

2 嵌套订阅永远不是一个可行的方法。我推荐这种方法:this.http.get('/api/people/1').pipe(  switchMap(character => this.http.get(character.homeworld).pipe(    map(homeworld => ({ ...character, homeworld })),  )),).subscribe(character => this.loadedCharacter = character);编辑:对于你的大学this.http.get('/api/people/1').pipe(  switchMap(character => this.http.get(character.university).pipe(    map(university => ({ ...character, university})),  )),).subscribe(character => this.loadedCharacter = character);甚至连锁大学和家乡的请求this.http.get('/api/people/1').pipe(  switchMap(character => this.http.get(character.homeworld).pipe(    map(homeworld => ({ ...character, homeworld })),    // catchError(err => of({ ...character, homeworld: dummyHomeworld })),  )),  switchMap(character => this.http.get(character.university).pipe(    map(university => ({ ...character, university})),  )),).subscribe(character => this.loadedCharacter = character);

素胚勾勒不出你

switchmap您可以尝试使用和来更轻松地进行链接和错误处理的解决方案forkJoin。这将有助于保持代码干净,以防链不断增长成深嵌套。    this.http      .get("/api/people/1'")      .pipe(        catchError((err) => {          // handle error        }),        switchMap((character) => {          return forkJoin({            character: of(character),            homeworld: this.http.get(character.homeworld)          });        })      )      .subscribe(({ character, homeworld }) => {        character.homeworld = homeworld;        this.loadedCharacter = character;      });编辑:场景 2this.http      .get("/api/people/1")      .pipe(        catchError((err) => {          console.log("e1", err);        }),        switchMap((character) => {          return forkJoin({            character: of(character),            homeworld: this.http.get(character.homeworld).pipe(              catchError((err) => {                console.log("e2", err);              })            )          });        })      )      .subscribe(({ character, homeworld }) => {        character.homeworld = homeworld;        this.loadedCharacter = character;      });您可以链接捕获错误或添加单独的错误处理函数,而无需调用下一个 API 调用。但我建议将后端逻辑抽象为角度服务并使用此方法。这将有助于保持易于阅读的结构。

慕田峪4524236

您可以通过检查状态码来检查第一次请求是否成功:&nbsp; ngOnInit() {&nbsp; &nbsp; this.http.get('/api/people/1').subscribe((character: HttpResponse<any>) => {&nbsp; &nbsp; &nbsp; // here you should look for the correct status code to check, in this example it's 200&nbsp; &nbsp; &nbsp; if (character.status === 200) {&nbsp; &nbsp; &nbsp; &nbsp; this.http.get(character.homeworld).subscribe(homeworld => {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; character.homeworld = homeworld;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.loadedCharacter = character;&nbsp; &nbsp; &nbsp; &nbsp; });&nbsp; &nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; // character is gonna contain the error&nbsp; &nbsp; &nbsp; &nbsp; console.log(character)&nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; });&nbsp; }
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript