angular - Hur man väntar inuti RxJS subscribe-metod


Inuti en RxJS subjects subscribe-callback vill jag await på en async funktion. Nedan är ett kodexempel som TypeScript-transpilern klagar på och säger:

Fel:(131, 21) TS2304:Kan inte hitta namnet '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
  });
}

Vanligtvis ser jag detta när jag försöker anropa await inuti en icke-async-funktion. Behöver jag på något sätt göra subscribe-callbacken async eller gör jag fel här? Funktionen saveToDatabase är async och returnerar ett löfte som löses till den primära nyckeln i databasen som skrevs till.

Svar #1

Du behöver inte använda await, och du behöver inte heller konvertera ditt Promise till en Observable.


Se detta Tweet från Ben Lesh :

Här är ett exempel med en mock för funktionen saveToDatabase :
(och den fungerande 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();

Utdata :

Svar #2

du kan bara direkt lägga till async-signatur till det anonyma funktionsanropet i 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
  });

Svar #3

Uppdatering: Hittade enkelt för engångslöften, använd bara toPromise framför abonnenten (blogg). Så för ovanstående fall blir det så här:

const title = await this.translate.get('MYBOOK-PAGE.PAGE_TITLE').toPromise();

Gammalt sätt: Här är min metod för att lösa detta problem

const title = await new Promise<string>(resolve => 
  this.translate.get('MYBOOK-PAGE.PAGE_TITLE')
   .subscribe(translated => {
     resolve(translated)
   }));

Här gör jag är att ändra min Observable till ett Promise

Observera: Här är det enda problemet att detta är en engångsshow, dvs. om du prenumererar en gång kommer du inte kunna få åtkomst till det igen. Passade mig, så delar här.

Relaterade artiklar