![](/img/trans.png)
[英]RxJS observables and generic types for Angular2(Typescript) http wrapper
[英]Chaining RxJS Observables from http data in Angular2 with TypeScript
在過去 4 年愉快地使用 AngularJS 1.* 之后,我目前正在嘗試自學 Angular2 和 TypeScript! 我不得不承認我討厭它,但我確信我的尤里卡時刻即將來臨......無論如何,我已經在我的虛擬應用程序中編寫了一個服務,它將從我編寫的提供 JSON 的虛假后端獲取 http 數據。
import {Injectable} from 'angular2/core';
import {Http, Headers, Response} from 'angular2/http';
import {Observable} from 'rxjs';
@Injectable()
export class UserData {
constructor(public http: Http) {
}
getUserStatus(): any {
var headers = new Headers();
headers.append('Content-Type', 'application/json');
return this.http.get('/restservice/userstatus', {headers: headers})
.map((data: any) => data.json())
.catch(this.handleError);
}
getUserInfo(): any {
var headers = new Headers();
headers.append('Content-Type', 'application/json');
return this.http.get('/restservice/profile/info', {headers: headers})
.map((data: any) => data.json())
.catch(this.handleError);
}
getUserPhotos(myId): any {
var headers = new Headers();
headers.append('Content-Type', 'application/json');
return this.http.get(`restservice/profile/pictures/overview/${ myId }`, {headers: headers})
.map((data: any) => data.json())
.catch(this.handleError);
}
private handleError(error: Response) {
// just logging to the console for now...
console.error(error);
return Observable.throw(error.json().error || 'Server error');
}
}
現在在一個組件中,我希望同時運行(或鏈接) getUserInfo()
和getUserPhotos(myId)
方法。 在 AngularJS 中,這很容易,因為在我的控制器中,我會做這樣的事情來避免“末日金字塔”......
// Good old AngularJS 1.*
UserData.getUserInfo().then(function(resp) {
return UserData.getUserPhotos(resp.UserId);
}).then(function (resp) {
// do more stuff...
});
現在,我已經嘗試在做我的組件類似的東西(更換.then
對於.subscribe
),但是我的錯誤控制台要瘋了!
@Component({
selector: 'profile',
template: require('app/components/profile/profile.html'),
providers: [],
directives: [],
pipes: []
})
export class Profile implements OnInit {
userPhotos: any;
userInfo: any;
// UserData is my service
constructor(private userData: UserData) {
}
ngOnInit() {
// I need to pass my own ID here...
this.userData.getUserPhotos('123456') // ToDo: Get this from parent or UserData Service
.subscribe(
(data) => {
this.userPhotos = data;
}
).getUserInfo().subscribe(
(data) => {
this.userInfo = data;
});
}
}
我顯然做錯了什么……我如何最好地使用 Observables 和 RxJS? 對不起,如果我問愚蠢的問題......但提前感謝您的幫助! 我還注意到在聲明我的 http 標頭時我的函數中的重復代碼......
對於您的用例,我認為flatMap
運算符是您所需要的:
this.userData.getUserPhotos('123456').flatMap(data => {
this.userPhotos = data;
return this.userData.getUserInfo();
}).subscribe(data => {
this.userInfo = data;
});
這樣,您將在收到第一個請求后執行第二個請求。 當您想使用前一個請求(前一個事件)的結果執行另一個請求時, flatMap
運算符特別有用。 不要忘記導入操作符才能使用它:
import 'rxjs/add/operator/flatMap';
這個答案可以為您提供更多詳細信息:
如果你只想使用subscribe
方法,你可以使用類似的東西:
this.userData.getUserPhotos('123456')
.subscribe(
(data) => {
this.userPhotos = data;
this.userData.getUserInfo().subscribe(
(data) => {
this.userInfo = data;
});
});
最后,如果您想並行執行兩個請求並在所有結果都得到通知時收到通知,您應該考慮使用Observable.forkJoin
(您需要添加import 'rxjs/add/observable/forkJoin'
):
Observable.forkJoin([
this.userData.getUserPhotos(),
this.userData.getUserInfo()]).subscribe(t=> {
var firstResult = t[0];
var secondResult = t[1];
});
你真正需要的是switchMap
操作符。 它獲取初始數據流(用戶信息),並在完成后將其替換為可觀察的圖像。
以下是我對您的流程的理解:
這是一個演示。 注意:我模擬了該服務,但代碼將適用於真正的服務。
ngOnInit() {
this.getPhotos().subscribe();
}
getUserInfo() {
return this.userData.getUserInfo().pipe(
tap(data => {
this.userInfo = data;
}))
}
getPhotos() {
return this.getUserInfo().pipe(
switchMap(data => {
return this.userData.getUserPhotos(data.UserId).pipe(
tap(data => {
this.userPhotos = data;
})
);
})
);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.