4 回答
TA貢獻(xiàn)1772條經(jīng)驗(yàn) 獲得超8個(gè)贊
首先,你的代碼可以工作,這很好——你可以保持原樣,一切都會(huì)好起來的。
另一方面,有一種多重改進(jìn)的方法將在未來幫助您和您的同事:
嘗試將與 http 相關(guān)的邏輯移至服務(wù)中,而不是在組件中調(diào)用 http - 這將幫助您將代碼拆分為與視圖相關(guān)的邏輯和與業(yè)務(wù)/獲取/轉(zhuǎn)換相關(guān)的邏輯。
盡量避免嵌套
subscribes - 您不僅會(huì)忽略Observables 的強(qiáng)大功能,而且還會(huì)將代碼綁定到某個(gè)流程,而無法在應(yīng)用程序中的某個(gè)地方重用這些行。返回Observable可能會(huì)幫助您“共享”請(qǐng)求的結(jié)果或以某種方式對(duì)其進(jìn)行轉(zhuǎn)換。flatMap/mergeMap,concatMap并switchMap以不同的方式工作,使您能夠按照自己想要的方式控制行為。不過,由于http.get()它們的工作原理幾乎相似,因此最好盡快開始學(xué)習(xí)那些組合運(yùn)算符。考慮一下在這種情況下您將如何處理錯(cuò)誤 - 如果您的第一次調(diào)用將導(dǎo)致錯(cuò)誤,會(huì)發(fā)生什么?
Observable有一個(gè)強(qiáng)大的機(jī)制來處理它們,同時(shí).subscribe允許您僅以一種方式處理錯(cuò)誤。
使用的示例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貢獻(xiàn)1810條經(jīng)驗(yàn) 獲得超4個(gè)贊
2 嵌套訂閱永遠(yuǎn)不是一個(gè)可行的方法。我推薦這種方法:
this.http.get('/api/people/1').pipe(
switchMap(character => this.http.get(character.homeworld).pipe(
map(homeworld => ({ ...character, homeworld })),
)),
).subscribe(character => this.loadedCharacter = character);
編輯:對(duì)于你的大學(xué)
this.http.get('/api/people/1').pipe(
switchMap(character => this.http.get(character.university).pipe(
map(university => ({ ...character, university})),
)),
).subscribe(character => this.loadedCharacter = character);
甚至連鎖大學(xué)和家鄉(xiāng)的請(qǐng)求
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貢獻(xiàn)1827條經(jīng)驗(yàn) 獲得超9個(gè)贊
switchmap您可以嘗試使用和來更輕松地進(jìn)行鏈接和錯(cuò)誤處理的解決方案forkJoin。這將有助于保持代碼干凈,以防鏈不斷增長(zhǎng)成深嵌套。
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;
});
編輯:場(chǎng)景 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;
});
您可以鏈接捕獲錯(cuò)誤或添加單獨(dú)的錯(cuò)誤處理函數(shù),而無需調(diào)用下一個(gè) API 調(diào)用。但我建議將后端邏輯抽象為角度服務(wù)并使用此方法。這將有助于保持易于閱讀的結(jié)構(gòu)。
TA貢獻(xiàn)1875條經(jīng)驗(yàn) 獲得超5個(gè)贊
您可以通過檢查狀態(tài)碼來檢查第一次請(qǐng)求是否成功:
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)
}
});
}
添加回答
舉報(bào)
