13

This page says "toPromise has been deprecated! (RxJS 5.5+)" but I've been using it lately with AngularFire2 (when I only want one result) like this:

const foo = await this.afs.doc(`docPath`).valueChanges().toPromise();

Should I not be doing this? If not, what is the await alternative?

UPDATE:

After the answer below I've changed this:

const foo = await this.afs.doc(`docPath`).valueChanges().toPromise();

...to this:

const foo = await (new Promise(resolve => this.afs.doc(`docPath`).valueChanges().pipe(first()).subscribe(result => resolve(result))));

Could someone please explain to me how this is an improvement?! Seems like a step backward to me.

Jus10
  • 14,519
  • 21
  • 52
  • 77
  • 1
    Possible duplicate of [Angular/rxjs: Why don't I have to import toPromise anymore?](https://stackoverflow.com/questions/46838807/angular-rxjs-why-dont-i-have-to-import-topromise-anymore) – zero298 Aug 03 '18 at 17:24
  • 4
    @zero298 don't dupe vote just because `toPromise` appears in both questions... – Jonas Wilms Aug 03 '18 at 17:25
  • @JonasW. Did you read the duplicate? "toPromise: now exists as a permanent method on Observable" I take that to mean it isn't deprecated. Would you rather me post an answer that says "It's not deprecated" or link to a question that says as much? – zero298 Aug 03 '18 at 17:28
  • @zero298 the question is 1 year old? – Jonas Wilms Aug 03 '18 at 17:30

3 Answers3

17

You just should put after pipe!

   .pipe(take(1)).toPromise
  • toPromise will retun promise ?? – Muhammed Albarmavi Aug 03 '18 at 17:34
  • 3
    Should I use `pipe(first())` instead? – Jus10 Aug 03 '18 at 18:00
  • How would we use this with await? – Jus10 Aug 03 '18 at 20:03
  • 8
    The `toPromise` method on `Observable` is **not** deprecated: https://github.com/ReactiveX/rxjs/blob/6.2.2/src/internal/Observable.ts#L329-L343 – cartant Aug 04 '18 at 02:09
  • Sorry I understood wrong, but you still can use toPromise but not to each observable, only after the pipe. In the new version of Rxjs, you put all your operatos inside a pipe and then after the pipe you can put the toPromise() – Adrian Lemes Caetano Aug 06 '18 at 14:20
  • @AdrianLemesCaetano hi adrian - is there a documentation link for this (which observable you can and cannot ? Most of the help/tutorials all have toPromise on the Observable. But I ran into this issue and resolved it with using pipe and take operator. But I'm not sure of the reason why this worked. Thanks – user3836415 Oct 02 '18 at 00:14
  • import { Observable } from 'rxjs'; import { first, take } from 'rxjs/operators'; const a = new Observable((observer) => { observer.next(5); observer.next(10);}); // We can use .toPromise chained with .pipe() to make it to work like promise a.pipe(take(1)).toPromise().then(value => console.log(value, "Im a promise")); //or we can use first or take(1) to make it to work like a promise a.pipe(take(1)).subscribe((value) => console.log(value, 'Observable')); – RK6 Oct 04 '18 at 08:18
  • 8
    Please remove this false claim about `toPromise` being deprecated. This is nowhere to be found, except this very answer. – Endrju Nov 07 '18 at 02:04
  • 8
    Guys, `toPromise()` is being deprecated in v7.0: https://medium.com/javascript-in-plain-english/rxjs-7-in-depth-32cc7bf3e5c – TetraDev Sep 04 '20 at 16:32
1

firstValueFrom and lastValueFrom is definitly a better alternative for many reasons:

  1. The naming is more readable and self explanatory.
  2. The additional ability to select either first or last value.
  3. The additional ability to declare a default value in case the observable didn't emit any

Reference: https://stackoverflow.com/a/69215890/5191209

0

Just a few other options for those who want to be crazy:

const foo = await this.afs.doc(`docPath`).valueChanges().pipe(take(1)).toPromise();

or

const foo = (await this.afs.doc('docPath').get().toPromise()).data();

or

const foo = (await this.afs.doc('docPath').get().pipe(take(1)).toPromise()).data();

or

const foo =  (await this.afs.doc('docPath').snapshotChanges().pipe(take(1))
.toPromise()).payload.data();

But the shortest is:

const foo = (await this.afs.doc('docPath').ref.get()).data();

And anywhere you can use take(1) you can use first() if you want to emit an error.

For more Firebase promises, see here.

J

Jonathan
  • 3,893
  • 5
  • 46
  • 77