当前位置: 首页 > 知识库问答 >
问题:

使用TypeScript链接Angular2中http数据的RxJS观测值

马弘益
2023-03-14

在愉快地使用AngularJS 1之后,我目前正在尝试自学Angular2和打字脚本。*在过去的4年里!我不得不承认我讨厌它,但我确信我的尤里卡时刻就在眼前。。。无论如何,我已经在我的虚拟应用程序中编写了一个服务,它将从我编写的提供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...
}); 

现在我尝试在我的组件中做一些类似的事情(替换。然后为。订阅)替换),但是我的错误控制台快疯了!

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

}

我显然做错了什么。。。如何最好地使用Observable和RxJS?对不起,如果我问了一些愚蠢的问题。。。但是提前谢谢你的帮助!我还注意到声明http头时函数中重复的代码。。。


共有2个答案

呼延卓
2023-03-14

您实际需要的是开关映射操作符。它获取初始数据流(用户信息),完成后,将其替换为可观察的图像。

以下是我如何理解您的流程

  • 获取用户信息
  • 从该信息获取用户Id
  • 使用用户Id获取用户照片

这里是一个演示。注意:我嘲笑了服务,但代码将与真正的服务一起工作。

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

郑旭
2023-03-14

对于您的用例,我认为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';

此答案可以为您提供更多详细信息:

  • 角度HTTP获取类型脚本错误HTTP。得到(…)。map不是[null]中的函数

如果您只想使用subscribe方法,您可以使用类似的方法:

this.userData.getUserPhotos('123456')
    .subscribe(
      (data) => {
        this.userPhotos = data;

        this.userData.getUserInfo().subscribe(
          (data) => {
            this.userInfo = data;
          });
      });

最后,如果你想并行执行两个请求,并在所有结果都被通知时,你应该考虑使用Observable.forkJoin(你需要添加导入'rxjs/add/观测/forkJoin'):

Observable.forkJoin([
  this.userData.getUserPhotos(),
  this.userData.getUserInfo()]).subscribe(t=> {
    var firstResult = t[0];
    var secondResult = t[1];
});
 类似资料:
  • 我有2个API调用第二个调用使用第一个调用返回的东西。有了promise,这很容易: 我将如何使用可观测数据来实现这一点?

  • 我是Rxjs可观测对象的新手,我需要使用Rxjs实现节流。 在下划线中,我们使用下面的行来实现这一点- 请协助如何使用可观察到的数据。

  • 在组件中: 在init上,我可以观察到 如何获取当前值,如?

  • 我有一个简单的api请求,它向一个对象返回一个可观察的对象,该对象中有一组项,每个项中都有一个链接。因此,我想在当前异步流中直接获取链接后面的数据,但我收到一个CORS错误,错误是: 这是否可能与我当前的函数?还是我误解了一些基本概念?

  • 我正在尝试使用 考虑以下代码 每当我试图打印出的结果时,它总是返回 即使我返回一个json对象。 如何打印的结果?

  • 我的后端有两个图形查询:,它返回一个家谱作为有孩子的节点,也可以有孩子等等,和,它返回给定人的图片。 我的目标是调用,迭代树,如果这个人被称为Alice,那么我想为这个人调用,并将信息添加到树中的节点。这应该为树上的所有爱丽丝做。 我的问题是,获取图片的调用是异步的,因此在信息添加到节点之前会返回数据。我没有按照这个问题中的建议使用,因为调用获取图片是在迭代树时发生的,我不能在的管道方法中调用它。