如何根据另一个可观察对象的结果订阅(或不订阅!)一个可观察对象

How to subscribe (or not!) to an observable depending of the result of another observable

使用 angular 10,在服务中,我有方法 getCurrentUser() 对我的 api 和 return 当前用户进行 http 调用作为可观察的(其中之一属性 是“isAdmin:boolean”),我有其他服务,我想在其中创建方法 getAllUsers ,该方法 return 所有用户列表 (user[]) 也可以观察到但是仅当当前用户是管理员时 (user.isAdmin = true)。我用 rxjs 运算符尝试了一些东西,比如 map、switchMap 和 flatMap,但我觉得我完全错了,你能给我一些提示吗?

这是我在第二个服务中尝试的:

@Injectable({
    providedIn: "root",
})
export class BackofficeService {

    constructor(private http: HttpClient, private userService: UserService) {}

    public getAllUsers(): Observable<User[]> {
        this.userService.getCurrentUser().pipe(
            map((user: User) => {
                if (user.roles.includes("admin")) {
                    return this.http.get<User[]>("/api/settings/users/all");
                } else throw new Error("User not admin.");
            })
        );
    }
}

我也不知道如何管理 getAllUsers() 的 return,因为如果用户不是管理员,有时它不会 return 任何东西。使用简单的“else throw new Error()”我得到了一个编译器错误,因为我声明 getAllUsers() 应该 return 一个 Observable。

然后在我的组件中我这样做:

@Component({
    selector: "app-users",
    templateUrl: "./users.component.html",
})
export class UsersComponent implements OnInit {
  public usersList: User[];
  constructor(private boService: BackofficeService) {}

    ngOnInit(): void {
    this.boService
      .getAllUsers()
      .subscribe((users?: User[]) => {
        if(users){
          this.usersList = users;
        }
      })
    }
}

如果用户不是管理员,一个简单的解决方案是 return null,方法是分离两个调用(getAdmin() 和 getAllUsers())。

@Injectable({
    providedIn: "root",
})
export class BackofficeService {

    constructor(private http: HttpClient, private userService: UserService) {}

    public getAdmin(): Observable<User> {
        return this.userService.getCurrentUser().pipe(
            map((user: User) => {
                if (user.roles.includes("admin")) {
                    return user;
                } else {
                    return null;
                }
            })
        );
    }
    
    public getAllUsers(): Observable<User[]> {
        return this.http
            .get<User[]>("/api/settings/users/all").pipe(
            map((users: User[]) => users);
    }
}

然后在组件中订阅两个,仅当第一个给出预期结果时才订阅第二个:

  ngOnInit(): void {
    this.boService
      .getAdmin()
      .subscribe((user: User) => {
        if (user) {
          this.boService
            .getAllUsers()
            .subscribe((users: User[]) => {
              console.log(users);
            });
        }
      });
  }

你犯的一个错误是 return 不是放在 Observable 上而是放在 Observable 结果上。

this.service.getUser().pipe(
  switchMap(user => user.isAdmin
    ? this.service.getAllUsers().pipe(users => [user, users])
    : of([user])
  )
).subscribe(([user, users]) => ... ) // users will be undefined if not admin

即使先例 post 回答了我的问题,我在这里 post 另一个对我有用的答案:有人告诉我,在这种情况下,好的概念是使管理逻辑在一个守卫,并在使用后台服务的组件的路由中添加这个守卫。 效果很好,似乎是很好的做法。