RXJS:返回嵌套的可观察变量 [英] RXJS: returning nested observables

查看:80
本文介绍了RXJS:返回嵌套的可观察变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试返回一个由User和Results组成的UserDetail对象,通过Account的accessToken检索User(所有检索均通过单个异步调用检索).目前,我仍想弄清楚如何导航到detailcomponent时如何返回该UserDetail对象(我知道由于调用是异步的,因此无法从字面上返回该对象,但是我需要在我的对象中使用该对象组件).

I'm trying to return a UserDetail object which consists of a User and Results, User is retrieved via the accessToken of Account (all retrieved via individual async calls). At the moment I'm stuck at figuring out how I can return this UserDetail object when I navigate to the detailcomponent (I know it is not possible to literally return the object since the call is async, but I need to use this object in my component).

下面的代码给我以下错误:

The code below gives me the following error:

类型'Observable'不可分配给类型可观察"

Type 'Observable' is not assignable to type 'Observable'

我已经尝试过使用管道和映射,因为我已经阅读了这是如何将异步调用返回"到调用该函数的组件的方法.然后,该组件应该可以处理订阅,但是如果不产生错误,我什至无法做到这一点.

I tried using pipes and maps since I've read this is how I should 'return' async calls to the component calling the function. The component is then supposed to handle the subscription, but I can't even get that far without creating errors.


@Injectable({
  providedIn: 'root'
})
export class UserResolver implements Resolve<UserDetails> {
  constructor(
    private as: AccountService,
    private rs: ResultService,
    private auth: AuthService
  ) {}

  resolve(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<UserDetails> {
    return this.as.getAccount(route.params['id']).pipe(
      map((acc: Account) => {
        this.as.getUserDetails(acc.access_token).pipe(
          map((user: User) => {
            if (user != null) {
              this.rs.getResults(this.auth.token).pipe(
                map((res: Result[]) => {
                  const ud: UserDetails = {
                    user,
                    results: res.filter(x => x.userId === acc.uid)
                  };
                  return of(ud);
                })
              );
            }
          })
        );
      })
    );

推荐答案

尝试使用 switchMap 而不是 map . map 只是将一个值转换为另一个值,而 switchMap 允许您切换到另一个可观察值.

Try using switchMap instead of map. map simply transforms one value into another, whereas switchMap allows you to switch to another observable.

对所发生的事情一无所知,我想你想要这样的东西:

Without knowing too much about what's going on, I think you want something like this:

let user: User;
let account: Account;
return this.as.getAccount(route.params['id']).pipe(
  tap((acc: Account) => account = account),
  switchMap((acc: Account) => this.as.getUserDetails(acc.access_token)),
  // this filter will stop the next steps from running if the user is null
  // it will also mean a value isn't emitted
  // if you want to emit a null, you will need to modify the pipe
  filter((u: User) => u !== null),
  tap((u: User) => user = u),
  switchMap((u: User) => this.rs.getResults(this.auth.token))
  map((res: Result[]) => {
    const ud: UserDetails = {
      user,
      results: res.filter(x => x.userId === account.uid)
    };
    return ud;
  })
);

注意它不再像您那样缩进,而是一系列管道运算符.每当您要切换到新的可观察对象时,请使用 switchMap concatMap .我们仅使用 map 将最后一个可观察到的结果映射到我们要从函数返回的值.

Notice how it's no longer indented like yours, but a sequence of pipe operators. Whenever you want to switch to a new observable, use switchMap or concatMap. We are only using map to map the result of the last observable to the value that we want to return from the function.

每当需要将状态保存到管道中间时,我都会使用tap来将其分配给变量.

Whenever state needs to be saved out of the middle of a pipe, I am using tap to assign it to a variable.

此外,您正在(可能)对 this.rs.getResults(this.auth.token)进行冗余调用.调用不会根据 id 参数的不同而改变,因此您只需获取一次,然后在后续调用中从缓存中读取即可.

Also, you are making (possibly) redundant calls to this.rs.getResults(this.auth.token). The call doesn't change based on the what the id param is, so you could just fetch once, and read from a cache on subsequent calls.

concatMap 也是一个选项.它们略有不同.两者都足以满足此答案的目的-我将不对您的用例进行假设.

concatMap is also an option. They are slightly different. Both are sufficient for the purposes of this answer - I'm not going to make assumptions about your use case.

这篇关于RXJS:返回嵌套的可观察变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆