如何在 Angular2 中进行嵌套的 Observable 调用 [英] How to make nested Observable calls in Angular2

查看:21
本文介绍了如何在 Angular2 中进行嵌套的 Observable 调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在进行嵌套的 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 的运算符.您的示例非常冗长,并且以不应该使用的方式使用 flatMapmap .此外,您的第一个示例无法正常工作,因为您没有订阅 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屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆