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));
You can use Observables with Promises and with async/await to benefit from the strengths of each of those tools.
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With