Bir Rx Observable'da nasıl "bekleyebilirim"?


111

Gözlenebilir bir yerde beklemek istiyorum, örneğin

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

Saf bir girişim, beklemenin hemen çözülmesine ve yürütmeyi engellememesine neden olur

Düzenleme: Tam kullanım amacım için sözde kod:

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

Diğer kodu başka bir ayrı işleve taşıyabileceğimi ve abone geri aramasına geçirebileceğimi anlıyorum, ancak bundan kaçınmayı umuyorum.


Kalan kodu (kaynak için beklemek istediğiniz) bir .subscribe()yöntem çağrısına taşıyamaz mısınız?
StriplingWarrior

Yanıtlar:


133

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

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

Notu düzenle: Bu yanıt, başlangıçta .take (1) kullanıyordu, ancak akış bir değer gelmeden önce biterse Promise'in asla çözülmemesi sorununu ortadan kaldıran .first () olarak değiştirildi.


3
Take (1) yerine kullanabilir await observable.first().toPromise();misiniz?
2016

15
@apricity Tamamlandığında herhangi bir değer yoksa, first()reddedilir ve take(1)bekleyen sözle sonuçlanır.
Estus Flask

6
@apricity @AgentME Aslında take(1)ne ya da first()böyle durumlarda KULLANMAMALISINIZ . Tam olarak BİR olay olmasını beklediğiniz için single(), 1'den fazla olması durumunda bir istisna atacak olanı kullanmalı ve hiçbiri olmadığında bir istisna atmamalısınız . Birden fazla varsa, kodunuzda / veri modelinizde büyük olasılıkla yanlış bir şeyler vardır. Single kullanmazsanız, daha fazlası olduğuna dair uyarı vermeden, rastgele dönen ilk öğeyi seçersiniz. Her zaman aynı sırayı korumak için yukarı akış veri kaynağındaki yükleminize dikkat etmeniz gerekir.
ntziolis

3
İçe aktarımı unutmayın:import 'rxjs/add/operator/first';
Stephanie

7
Artık toPromise () kullanımdan kaldırıldı, bunu nasıl yapmalıyız?
Jus10

26

Muhtemelen olmalı

await observable.first().toPromise();

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

Observable.empty().first().toPromise()buna EmptyErrorgöre ele alınabilecek bir reddedilme ile sonuçlanacaktır , çünkü gerçekten bir değeri yoktu.

Ve değerli bir Observable.empty().take(1).toPromise()çözünürlükle sonuçlanacaktır undefined.


Aslında take(1)edecek değil bekleyen bir söz verir. Çözülmüş bir söz verecektir undefined.
Johan t Hart

Fark ettiğin için teşekkürler, bu doğru. Gönderinin neden farklı olduğundan emin değilim, muhtemelen davranış bir noktada değişti.
Estus Flask

8

awaitBir söz vermen gerekecek , bu yüzden kullanmak isteyeceksin toPromise(). Bkz bu ilgili daha fazla ayrıntı için toPromise().


5

Eğer toPromisesizin için uygun bulunmamaktadır, kullanabilirsiniz .pipe(take(1)).toPromiseama Gördüğünüz burada Kullanımdan kaldırıldığı değil.

Öyleyse lütfen şu şekilde kullanın toPromise(RxJs 6):

//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);
  });

eşzamansız / bekleme ö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 .

Ve lütfen bu yanlış iddianın toPromisekullanımdan kaldırıldığını kaldırın .


1

Yeni firstValueFrom()veya lastValueFrom()yerine kullanın, toPromise()burada belirtildiği gibi, RxJS 7'den itibaren kullanımdan kaldırılmıştır ve RxJS 8'de kaldırılacaktır.

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

Bakınız: https://indepth.dev/rxjs-heads-up-topromise-is-being-deprecated/

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.