-2

Assuming I have an http request to get users:

users$: Observable<User[]>;

ngOnInit() {
  users$ = this.users_service.get_all_users();
}

I subscribe to this observable using async pipe in my template:

<div *ngFor="let user of users$ | async">

I want to change an email of a single user with another http request, but keep a single subscription. The problem is that the http request that changes the email hasn't been defined at the point I created users$ observable. what I did is:

users$: Observable<User[]>;
update_user_event$ = new BehaviorSubject(null);
users_with_updates$: Observable<User[]>;

ngOnInit() {
  users$ = this.users_service.get_all_users();

  users_with_updates$ = Observable.combineLatest(users$, update_user_event$)
  .switchMap(([users, update_user_event]) => {
    return Observable.of(users)
  })
}
update_user(user) {
  this.user_service.update_user(user)
  .toPromise() // <== I don't want to subscribe to this request. Is there a way to combine it with `users$` without subscribing?
  .then(updated_user => {
    for(let key of user) {
      user[key] = updated_user[key]
    }
    update_user_event$.next(null);
  })
}

As you can see I subscribe to update_user using toPromise(). I can not combine this request ahead since it is not defined until it is requested. I have been searching all over the internet but couldn't find an agreed best practice.
How do you think it should be done? Thanks

4

1 回答 1

2

I recommend to store the users in a subject. The initial call as well any update will call next on the BehaviorSubject.

private users: BehaviorSubject<User[]> = new BehaviorSubject<User[]>([]);
users$: Observable<User[]> = this.users.asObservable();

ngOnInit() {
  this.users_service.get_all_users().subscribe(this.users);
}

update_user(user) {
  this.user_service.update_user(user)
  .toPromise()
  .then(user => {
    const currentUsers = this.users.value;
    // TODO: change user in currentUsers
    this.users.next(currentUsers);
  })
}
于 2020-11-11T10:32:37.663 回答