加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

Angular2:使用Observables进行多次同步调用的最佳方法是什么?

发布时间:2020-12-17 06:53:53 所属栏目:安全 来源:网络整理
导读:在我使用Promises进行服务调用之前,我正在研究Angular2 / 4中的Observables. 我想知道进行多个同步调用的最佳方法是什么. 让我用一个例子来解释一下: 我的app组件有一个getUserInfo()方法,需要对3个不同的服务进行3次调用,这些服务相互依赖. getUserId():Nu
在我使用Promises进行服务调用之前,我正在研究Angular2 / 4中的Observables.

我想知道进行多个同步调用的最佳方法是什么.
让我用一个例子来解释一下:
我的app组件有一个getUserInfo()方法,需要对3个不同的服务进行3次调用,这些服务相互依赖.

getUserId():Number // return the logged in user userId from the session
getUserPermissions(userId):Array<String> // return a list of permission from the userId
getUserInfo(userId):String // return some additional info for the user

现在让我假设我有一个User对象如下:

export class User {
id: number;
name: string;
info: string;
permissions: array<string>;
}

我需要使用3个服务调用的结果创建一个User类的新实例,所以我需要运行:

> getUserId();
> getUserPermissions();
> getUserInfo();

通过Observable实现这一目标的最佳和最礼貌的方法是什么?

有了承诺,我会有这样的事情:

this._service.getUserId().then(r1 => {
  let userId: number = r1;
  this._service.getUserPermissions(userId).then(r2 => {
    let userPermissions: Array<String> = r2;
    this._service.getUserInfo(userId).then(r3 => {
      let userInfo: string = r3;
      let user: User = new User(userId,userInfo,userPermissions);
    });
  })
});

解决方法

我不能保证这是最好或最礼貌的方式,因为RxJs是一个如此强大的库,你可以用许多不同的方式获得相同的结果,但我会试一试.
我会选择两个选项.

假设您的服务看起来像这样:

userservice.ts

@Injectable()
export class UserService {

  constructor(private http: Http) { }

  getUserId(): Observable<{ id: number,name: string }> {
    return Observable.of({ id: 3,name: 'Bob' }).delay(300);
    /* 
     * replace with http:
     * return this.http.get('http://my.api.com/api/user/id').map(res => res.json());
     */
  }

  getUserPermission(userId: number): Observable<{ permissions: string[] }> {
    return Observable.of({ permissions: ['user','admin'] }).delay(300);
    /* return this.http.get(`http://my.api.com/api/user/${userId}/permissions`).map(res => res.json()); */
  }

  getUserInfo(userId: number): Observable<{ info: string }> {
    return Observable.of({ info: 'is a nice person'}).delay(300);
    /* return this.http.get(`http://my.api.com/api/user/${userId}/info`).map(res => res.json()); */
  }
}

请注意,这些方法返回JSON对象的Observables!
由于Angular http已经返回Observables,因此将它一直保持为Observable链可能是最容易和最干净的.
当然,您可以使用service方法内部的map-operator(f.e. .map(result => result.info))将返回类型设置为Observable< string>而不是Observable< {info:string}>.

switchMap

此方法适用于必须按特定顺序发生的请求.

this.userService.getUserId()
  .switchMap(userResult =>
    this.userService.getUserPermission(userResult.id)
    .switchMap(permissionsResult =>
      this.userService.getUserInfo(userResult.id)
        .map(infoResult => ({
          id: userResult.id,name: userResult.name,permissions: permissionsResult.permissions,info: infoResult.info
        }))
    )
  )
  .subscribe(v => console.log('switchmap:',v));

如果打开浏览器的网络选项卡,您将看到请求按顺序执行,这意味着每个请求必须在下一个请求开始之前完成.所以getUserId()必须在getUserPermission()启动之前完成,这反过来必须在getUserInfo()运行之前完成……依此类推.

您也可以使用mergeMap.唯一的区别是,当source observable发出新值时,switchMap可以取消正在进行的http请求.看here进行比较.

forkJoin

此方法允许您并行执行请求.

this.userService.getUserId()
  .switchMap(userResult => Observable.forkJoin(
    [
      Observable.of(userResult),this.userService.getUserPermission(userResult.id),this.userService.getUserInfo(userResult.id)
    ]
  ))
  .map(results => ({
    id: results[0].id,name: results[0].name,permissions: results[1].permissions,info: results[2].info
  }))
  .subscribe(v => console.log('forkJoin:',v));

由于forkJoin运行并行给出的所有Observable序列,因此如果请求(或至少其中一些请求)不相互依赖,则它是更好的选择.
在此示例中,getUserId() – 请求将首先运行,一旦完成,getUserPermission()和getUserInfo()将开始并行运行.

两种方法都将返回具有以下结构的对象:

{
    "id": 3,"name": "Bob"
    "permissions": [
        "user","admin"
    ],"info": "is a nice person"
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读