javascript - Bir Rx Observable üzerinde `await` nasıl kullanabilirim?


Bir gözlemlenebilir üzerinde bekleyebilmeyi isterim, örn.

const source = Rx.Observable.create(/* ... */)
//...
await source;

Saf bir deneme, await'in hemen çözülmesi ve yürütmeyi engellememesiyle sonuçlanır

Düzenleme: Tam amaçladığım kullanım durumu için sözde kod şudur:

if (condition) {
  await observable;
}
// a bunch of other code

Diğer kodu başka bir ayrı fonksiyona taşıyabileceğimi ve bunu subscribe geri çağrısına geçirebileceğimi anlıyorum, ama bunu yapmaktan kaçınmayı umuyorum.

Cevap #1

Bir sözü await etmek zorundasınız. Gözlemlenebilirin bir sonraki olayını bir söze dönüştürün ve onu bekleyin.

if (condition) {
  await observable.first().toPromise();
}

Notu düzenle: Bu cevap başlangıçta .take(1) kullanıyordu ama .first() kullanacak şekilde değiştirildi; bu, akış bir değer gelmeden önce sona ererse Promise’in asla çözülmeme sorununu önler.

RxJS v8 ile birlikte, toPromise kaldırılacaktır. Bunun yerine, yukarıdaki ifade await firstValueFrom(observable) ile değiştirilebilir.

Cevap #2

RxJS 7'den itibaren kullanımdan kaldırıldığı burada belirtildiği üzere ve RxJS 8'de kaldırılacak olan toPromise() yerine yeni firstValueFrom() veya lastValueFrom() yöntemlerini kullanın.

import { firstValueFrom} from 'rxjs';
import { lastValueFrom } from 'rxjs';

this.myProp = await firstValueFrom(myObservable$);
this.myProp = await lastValueFrom(myObservable$);

Bu, RxJS 7+ sürümünde mevcuttur

Bkz: https://indepth.dev/rxjs-heads-up-topromise-is-being-deprecated/

Cevap #3

Muhtemelen olması gerekiyor

await observable.first().toPromise();

Daha önce yorumlarda belirtildiği gibi, boş tamamlanmış gözlemlenebilir durumlarda take(1) ve first() operatörleri arasında önemli fark vardır.

Observable.empty().first().toPromise() EmptyError ile reddedilmesiyle sonuçlanır ve bu da buna göre yönetilebilir, çünkü gerçekten bir değer yoktu.

Ve Observable.empty().take(1).toPromise(), undefined değeri ile çözülmeyle sonuçlanacaktır.

Cevap #4

Düzenle:

.toPromise() artık RxJS 7'de kullanımdan kaldırıldı (kaynak: https://rxjs.dev/deprecations/to-promise)

Yeni cevap:

Kullanımdan kaldırılmış toPromise() metodunun yerine, yerleşik iki statik dönüştürme fonksiyonundan biri olan firstValueFrom veya lastValueFrom'u kullanmalısınız.

Örnek :

import { interval, lastValueFrom } from 'rxjs';
import { take } from 'rxjs/operators';
 
async function execute() {
  const source$ = interval(2000).pipe(take(10));
  const finalNumber = await lastValueFrom(source$);
  console.log(`The final number is ${finalNumber}`);
}
 
execute();
 
// Expected output:
// "The final number is 9"

Eski cevap:

Eğer toPromise sizin için kullanımdan kaldırıldıysa, .pipe(take(1)).toPromise kullanabilirsiniz ama gördüğünüz gibi burada kullanımdan kaldırılmamış.

Lütfen dediği gibi sadece toPromise (RxJs 6) kullanın:

//return basic observable
const sample = val => Rx.Observable.of(val).delay(5000);
//convert basic observable to promise
const example = sample('First Example')
  .toPromise()
  //output: 'First Example'
  .then(result => {
    console.log('From Promise:', result);
  });

async/await örneği:

//return basic observable
const sample = val => Rx.Observable.of(val).delay(5000);
//convert basic observable to promise
const example = await sample('First Example').toPromise()
// output: 'First Example'
console.log('From Promise:', result);

Daha fazlasını buradan okuyun.

Cevap #5

Bir sözün yerine getirilmesini await etmeniz gerekecek, bu yüzden toPromise() kullanmak isteyeceksiniz. toPromise() hakkında daha fazla detay için buna bakın.

İlgili makaleler