Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return observable from async function

TLDR; I have a Promise collection().add() which resolves to an object DocumentReference with a listener function onSnapshot() that emits data.

I need to return an Observable which, upon subscription, calls the Promise, subscribes to the listener function on the resolved object, and broadcasts the values from the listener to subscriber.next()

Context: I am trying to declare a function that creates a Firestore document, then returns an Observable with the document data, using the onSnapshot() function on its DocumentReference returned by collection().add().

Based on: https://github.com/EddyVerbruggen/nativescript-plugin-firebase/blob/f6972433dea48bf1d342a6e4ef7f955dff341837/demo-ng/app/item/items.component.ts#L175-L185

async create(project) {
    const ref = await this.db.collection('projects').add(project);
    return new Observable(subscriber => {
        ref.onSnapshot(doc => {
            // ...
            subscriber.next(doc.data());
        });
    });
}

Current behaviour:async/await always returns a Promise, I need the function to return an observable.

Expected: I need a slice of data from the ref.onSnapshot() callback, in this case doc.data(), to use it in my template, e.g.

// ... 

this.service.create(project).subscribe(project => console.log(project));
like image 308
Friso Hoekstra Avatar asked Aug 13 '19 08:08

Friso Hoekstra


People also ask

Does async await work with observables?

You can use Observables with Promises and with async/await to benefit from the strengths of each of those tools.

Is Observable asynchronous?

An observable produces values over time. An array is created as a static set of values. In a sense, observables are asynchronous where arrays are synchronous. In the following examples, → implies asynchronous value delivery.

Are RXJS observables async?

A common misconception in Angular development is regarding whether observables are synchronous or asynchronous. A lot of (even experienced Angular developers) think that observables are async, but the truth is that they can be… Both synchronous and asynchronous.

Can we use async await in angular?

Using Async/Await in Angular Basically, Async/Await works on top of Promise and allows you to write async code in a synchronous manner. It simplifies the code and makes the flow and logic more understandable.


1 Answers

In your implementation create returns a promise, since as you pointed out it needs to work async. If this is a fact then you have to modify the context calling create: simply make the calling function async as well and add await before the call to create: await create(...).

As an alternative, if you want to return an observable no matter what, you have to stop awaiting the db.collection().add() and remove the async before create. Then you can return the observable directly and inside the .then function of db.collection().add() you could update the observable with doc.data():

create(project) {
    return new Observable(subscriber => {
        this.db.collection('projects').add(project)
           .then(ref => {
                ref.onSnapshot(doc => {
                    // ...
                    subscriber.next(doc.data());
                });
           });
    });
}

Note that await is just one way to handle a Promise. The more classical way is attaching a callback to its .then. Note that .then again returns a Promise which again has a .then and so on - this is how Promises are defined.

like image 91
B M Avatar answered Sep 20 '22 21:09

B M