Inside of an RxJS subject's subscribe callback, I want to await
on an async
function. Below is a code example which the typescript transpiler complains about saying:
Error:(131, 21) TS2304:Cannot find name 'await'.
async ngOnInit() {
this.subscriber = dateSubscription.subscribe((date: Date) => {
let dbKey = await this._someService.saveToDatabase(someObject);
// wait for db write to finish before evaluating the next code
// ... some other code here
});
}
Usually I see this when trying to call await inside a non async
function. Do I somehow need to make the subscribe callback async
or am I going about this wrong? The function saveToDatabase
is async
and returns a promise resolving to the database primary key that was written to.
you can achieve this using toPromise method. It is also a great way to handle asynchronous operations. Just remove the subscribe and add this method and add the async keyword in the method from where you are calling this method. const response = await this.
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.
You have to pass a promise to await . Convert the observable's next event to a promise and await that.
RxJS is a library for composing asynchronous and event-based programs by using observable sequences. It provides one core type, the Observable, satellite types (Observer, Schedulers, Subjects) and operators inspired by Array#extras (map, filter, reduce, every, etc) to allow handling asynchronous events as collections.
you can just directly add async signature to the anonymous function call in subscribe
this.subscriber = dateSubscription.subscribe(async (date: Date) => {
let dbKey = await this._someService.saveToDatabase(someObject);
// wait for db write to finish before evaluating the next code
// ... some other code here
});
You do not need to use await
, nor need to convert your Promise
to an Observable
.
Here's an example with a mock for the function saveToDatabase
:
(and the working Plunkr : https://plnkr.co/edit/7SDLvRS2aTw9gYWdIznS?p=preview)
const { Observable } = Rx;
const saveToDatabase = (date) =>
new Promise(resolve =>
setTimeout(() =>
resolve(`${date} has been saved to the database`),
1000));
const date$ = Observable.of(new Date()).delay(1000);
date$
.do(x => console.log(`date received, trying to save it to database ...`))
.switchMap(date => saveToDatabase(date))
.do(console.log)
.subscribe();
Output :
Update:
Found easy for one time promises just use toPromise
in front of the subscriber (blog). So for the above case it will be like this:
const title = await this.translate.get('MYBOOK-PAGE.PAGE_TITLE').toPromise();
Old way: Here's my method of solving this issue
const title = await new Promise<string>(resolve =>
this.translate.get('MYBOOK-PAGE.PAGE_TITLE')
.subscribe(translated => {
resolve(translated)
}));
Here what I'm doing is changing my Observable to a Promise
Note: Here the only problem is this is one time show ie. if you subscribe once you won't able to access it again. Suited me so sharing here.
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