4 回答

TA貢獻1772條經驗 獲得超8個贊
首先,你的代碼可以工作,這很好——你可以保持原樣,一切都會好起來的。
另一方面,有一種多重改進的方法將在未來幫助您和您的同事:
嘗試將與 http 相關的邏輯移至服務中,而不是在組件中調用 http - 這將幫助您將代碼拆分為與視圖相關的邏輯和與業務/獲取/轉換相關的邏輯。
盡量避免嵌套
subscribe
s - 您不僅會忽略Observable
s 的強大功能,而且還會將代碼綁定到某個流程,而無法在應用程序中的某個地方重用這些行。返回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);
})
}
}

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

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

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)
}
});
}
添加回答
舉報