简体   繁体   中英

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, eg

// ... 

this.service.create(project).subscribe(project => console.log(project));

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 await ing 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 Promise s are defined.

Try using from operator to create observable directly from Promise. Here are docs for it: https://www.learnrxjs.io/operators/creation/from.html

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM