如何在 Angular2 中进行嵌套的 Observable 调用 [英] How to make nested Observable calls in Angular2
问题描述
我在进行嵌套的 Observable 调用时遇到了一些麻烦.我的意思是调用 http 服务来检索用户,然后从用户那里获取 id 以进行另一个 http 调用,最后在屏幕上呈现结果.
1) HTTP GET 1 : 获取用户
2) HTTP GET 2:获取用户的首选项,将唯一标识符作为参数传递
这在组件 Blah.ts
中转换为以下代码:
版本 1 - 此代码不显示任何内容
ngOnInit() {this.userService.getUser().flatMap(u => {this.user = u;//保存用户返回 Observable.of(u);//传递 Observable}).flatMap(u => this.userService.getPreferences(this.user.username))//获取这个用户的首选项.map(p => {this.preferences = p;//保存首选项});}
version 2 - 此代码有效,但对我来说似乎是错误的方法:
this.userService.getUser().subscribe(u => {this.user = u;this.userService.getPreferences(this.user.username).subscribe(prefs => {this.preferences = 首选项;});});
这是模板:
用户
<div class="row col-md-12"><div class="col-md-6"><div class="panel panel-default"><div class="panel-heading"><h3 class="panel-title">用户详情</h3>
<div class="panel-body"><table class="table table-condensed"><头><tr><th>用户名</th><th>全名</th><th>已启用</th></tr></thead>
<tr><td>{{user?.username}}</td><td>{{user?.fullName}}</td><td>{{user?.enabled}}</td></tr></tbody><!-- 第 1 列的结尾--><div class="col-md-6"><div class="panel panel-default"><div class="panel-heading"><h3 class="panel-title">用户偏好</h3>
<div class="panel-body"><table class="table table-condensed"><头><tr><th>语言</th><th>Locale</th></tr></thead>
<tr><td>{{preferences?.preferences?.get('language')}}</td><td>{{preferences?.preferences?.get('locale')}}</td></tr></tbody><!-- 第 2 列结束-->
<!-- 第 1 行的结尾-->
我认为展示服务没有任何意义,它只是让 http get()
调用如下:
http.get('http://blablah/users/').map((响应) => response.json())
请提出定义 Observable 链的最佳工作方法.
您应该稍微阅读一下 rxjs 的运算符.您的示例非常冗长,并且以不应该使用的方式使用 flatMap
和 map
.此外,您的第一个示例无法正常工作,因为您没有订阅 Observable.
这将满足您的需求:
ngOnInit() {this.userService.getUser().pipe(点击(u => this.user = u),flatMap(u => this.userService.getPreferences(u.username))).subscribe(p => this.preferences = p);}
遗产:
在 5.5 版之前 rxjs 专门使用基于原型的运算符.此代码在功能上等同于上述代码:
ngOnInit() {this.userService.getUser().do(u => this.user = u)//.do 只是调用函数.不操作流,返回值被忽略..flatMap(u => this.userService.getPreferences(u.username)).subscribe(p => this.preferences = p);}
I am having some troubles making nested Observable calls. By that I mean a call to a http service that retrieve a user, then getting the id from the user to make another http call, and finally render the results on screen.
1) HTTP GET 1 : get the User
2) HTTP GET 2: get the User's preferences passing a unique identifier as a parameter
This translates into the following code in component Blah.ts
:
version 1 - this code does not display anything
ngOnInit() {
this.userService.getUser()
.flatMap(u => {
this.user = u; // save the user
return Observable.of(u); // pass on the Observable
})
.flatMap(u => this.userService.getPreferences(this.user.username)) // get the preferences for this user
.map(p => {
this.preferences = p; // save the preferences
});
}
version 2 - this code works but seems the wrong approach to me:
this.userService.getUser().subscribe(u => {
this.user = u;
this.userService.getPreferences(this.user.username).subscribe(prefs => {
this.preferences = prefs;
});
});
And this is the template:
<h3>User</h3>
<div class="row col-md-12">
<div class="col-md-6">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">User details</h3>
</div>
<div class="panel-body">
<table class="table table-condensed">
<thead>
<tr>
<th>Username</th>
<th>Full Name</th>
<th>Enabled</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{user?.username}}</td>
<td>{{user?.fullName}}</td>
<td>{{user?.enabled}}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<!-- end of col 1-->
<div class="col-md-6">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">User preferences</h3>
</div>
<div class="panel-body">
<table class="table table-condensed">
<thead>
<tr>
<th>Language</th>
<th>Locale</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{preferences?.preferences?.get('language')}}</td>
<td>{{preferences?.preferences?.get('locale')}}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<!-- end of col 2-->
</div>
<!-- end of row 1-->
I don't think there is any point in showing the service, which simply makes http get()
calls like:
http.get('http://blablah/users/')
.map((response) => response.json())
Please suggest which is the best working approach to define a chain of Observables.
You should read up on rxjs's operators a little. Your examples are very verbose and use flatMap
and map
in a way they're not supposed to be used. Also your first example can't work, because you're not subscribing to the Observable.
This will do what you need:
ngOnInit() {
this.userService.getUser().pipe(
tap(u => this.user = u),
flatMap(u => this.userService.getPreferences(u.username))
).subscribe(p => this.preferences = p);
}
legacy:
Before version 5.5 rxjs exclusively used prototype-based operators. This code is functionally equivalent to the above:
ngOnInit() {
this.userService.getUser()
.do(u => this.user = u) //.do just invokes the function. does not manipulate the stream, return value is ignored.
.flatMap(u => this.userService.getPreferences(u.username))
.subscribe(p => this.preferences = p);
}
这篇关于如何在 Angular2 中进行嵌套的 Observable 调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!