亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Angular 中多個 HTTP 請求的最佳方式

Angular 中多個 HTTP 請求的最佳方式

德瑪西亞99 2023-08-05 11:01:17
我正在嘗試一一發送 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但如果這個方法解決了我的問題似乎更具可讀性。任何想法?
查看完整描述

4 回答

?
料青山看我應如是

TA貢獻1772條經驗 獲得超8個贊

首先,你的代碼可以工作,這很好——你可以保持原樣,一切都會好起來的。

另一方面,有一種多重改進的方法將在未來幫助您和您的同事:

  1. 嘗試將與 http 相關的邏輯移至服務中,而不是在組件中調用 http - 這將幫助您將代碼拆分為與視圖相關的邏輯和與業務/獲取/轉換相關的邏輯。

  2. 盡量避免嵌套subscribes - 您不僅會忽略Observables 的強大功能,而且還會將代碼綁定到某個流程,而無法在應用程序中的某個地方重用這些行。返回Observable可能會幫助您“共享”請求的結果或以某種方式對其進行轉換。

  3. flatMap/mergeMap,concatMapswitchMap以不同的方式工作,使您能夠按照自己想要的方式控制行為。不過,由于http.get()它們的工作原理幾乎相似,因此最好盡快開始學習那些組合運算符。

  4. 考慮一下在這種情況下您將如何處理錯誤 - 如果您的第一次調用將導致錯誤,會發生什么?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);

    })

  }

}


查看完整回答
反對 回復 2023-08-05
?
蝴蝶不菲

TA貢獻1810條經驗 獲得超4個贊

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);


查看完整回答
反對 回復 2023-08-05
?
素胚勾勒不出你

TA貢獻1827條經驗 獲得超9個贊

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;

      });

編輯:場景 2


this.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 調用。但我建議將后端邏輯抽象為角度服務并使用此方法。這將有助于保持易于閱讀的結構。


查看完整回答
反對 回復 2023-08-05
?
慕田峪4524236

TA貢獻1875條經驗 獲得超5個贊

您可以通過檢查狀態碼來檢查第一次請求是否成功:


  ngOnInit() {

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

      // here you should look for the correct status code to check, in this example it's 200

      if (character.status === 200) {

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

          character.homeworld = homeworld;

          this.loadedCharacter = character;

        });

      } else {

        // character is gonna contain the error

        console.log(character)

      }

    });

  }


查看完整回答
反對 回復 2023-08-05
  • 4 回答
  • 0 關注
  • 215 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號