2

I am pretty new in Angular and RxJS and in my code I have the following problem.

Into the ngOnInit() method I have this code snippet:

this.usersService.getAllUsers().toPromise().then(people => {
    this.people = people;
    this.peopleStr = people.map(person => person.complete_name);
    this.loading = false;
});

That is calling the getAllUsers() method on the UserService class:

getAllUsers(): Observable<any[]> {
    this.usersList = this.db.collection('Users').snapshotChanges();
    return this.usersList;
}

As you can see this getAllUsers() method return an Observable so to use the then() function I converted the result of the call to this getAllUsers() into a Promise using the toPromise().

But it seems it is not working because, using the debugger, I see that it never execute the code inside the then() function

Why? What is wrong? What am I missing? How can I fix it?

AndreaNobili
  • 40,955
  • 107
  • 324
  • 596
  • [please see if this help you](https://stackoverflow.com/a/36777294/12163165) – user12163165 Sep 13 '20 at 15:58
  • If you're new to RxJS, I understand it's easy to convert observables to promises using `toPromise()` and take the easy route out. But `toPromise()` is [being deprecated](https://indepth.dev/rxjs-heads-up-topromise-is-being-deprecated/) in RxJS 7 (next major release) and out in RxJS 8. You're better off learning the observables and _subscribing_ to use it's notifications. Also observables provide much more functionality to control and adjust the flow of data using various [operators](https://rxjs-dev.firebaseapp.com/guide/operators). – ruth Sep 13 '20 at 16:37

1 Answers1

3

The Promise returned from toPromise will not resolve until the underlying observable completes.

So you have two choices

Remove toPromise altogether and use subscribe. This will trigger on every emission.

this.usersService.getAllUsers().subscribe(people => {
    this.people = people;
    this.peopleStr = people.map(person => person.complete_name);
    this.loading = false;
});

Or use first() to take the first value emitted and complete after the first emission.

this.usersService.getAllUsers().pipe(first()).toPromise().then(people => {
    this.people = people;
    this.peopleStr = people.map(person => person.complete_name);
    this.loading = false;
});

But as toPromiseis being deprecated, so if you want only the first emission you better make it as follows:

this.usersService.getAllUsers().pipe(first()).subscribe(people => {
    this.people = people;
    this.peopleStr = people.map(person => person.complete_name);
    this.loading = false;
});

The last snippet is the same as the toPromise one.

So it depends on if you are interested in all emissions or only the first one.

Sherif Elmetainy
  • 4,034
  • 1
  • 13
  • 22