Chciałbym móc czekać na obserwowalny, np
const source = Rx.Observable.create(/* ... */)
//...
await source;
Naiwna próba skutkuje natychmiastowym rozstrzygnięciem oczekiwania i nie blokowaniem wykonania
Edycja: pseudokod dla mojego pełnego zamierzonego przypadku użycia to:
if (condition) {
await observable;
}
// a bunch of other code
Rozumiem, że mogę przenieść drugi kod do innej oddzielnej funkcji i przekazać go do wywołania zwrotnego subskrypcji, ale mam nadzieję, że uda mi się tego uniknąć.
javascript
rxjs
ecmascript-7
CheapSteaks
źródło
źródło
.subscribe()
wywołania metody?Odpowiedzi:
Musisz przekazać obietnicę
await
. Zamień następne zdarzenie obserwowalnego na obietnicę i czekaj na to.Uwaga dotycząca edycji: ta odpowiedź pierwotnie używała .take (1), ale została zmieniona na .first (), co pozwala uniknąć problemu z obietnicą, która nigdy nie została rozwiązana, jeśli strumień kończy się przed pojawieniem się wartości.
źródło
await observable.first().toPromise();
?first()
spowoduje odrzucenie itake(1)
oczekującą obietnicę.take(1)
anifirst()
w takich przypadkach. Ponieważ spodziewasz się dokładnie JEDNEGO zdarzenia, powinieneś użyć,single()
który zgłosi wyjątek, jeśli jest więcej niż 1, nie rzucając wyjątku, gdy go nie ma. Jeśli jest więcej niż jeden, prawdopodobnie coś jest nie tak w Twoim kodzie / modelu danych itp. Jeśli nie użyjesz pojedynczego, w końcu arbitralnie wybierzesz pierwszy element, który powróci bez ostrzeżenia, że jest ich więcej. Musisz uważać w swoim predykacie na nadrzędnym źródle danych, aby zawsze zachować tę samą kolejność.import 'rxjs/add/operator/first';
Prawdopodobnie tak musi być
Jak zauważono we wcześniejszych komentarzach, istnieje zasadnicza różnica między operatorami
take(1)
afirst()
, gdy występuje pusta wypełniona obserwowalna.Observable.empty().first().toPromise()
spowoduje odrzucenie, przyEmptyError
czym można to odpowiednio potraktować, ponieważ tak naprawdę nie było wartości.I
Observable.empty().take(1).toPromise()
spowoduje rozdzielczość zundefined
wartością.źródło
take(1)
będzie nie uzyskując oczekującego obietnicy. Przyniesie obietnicę rozwiązanąundefined
.Będziesz potrzebował
await
obietnicy, więc będziesz chciał użyćtoPromise()
. Zobacz to, aby uzyskać więcej informacjitoPromise()
.źródło
Jeśli
toPromise
jest przestarzały, możesz go użyć,.pipe(take(1)).toPromise
ale jak widać tutaj, nie jest on wycofany.Więc proszę, po
toPromise
prostu użyj (RxJs 6), jak powiedziano:przykład async / await:
Przeczytaj więcej tutaj .
I proszę usuń to błędne twierdzenie, że
toPromise
jest przestarzałe.źródło
Użyj nowego
firstValueFrom()
lublastValueFrom()
zamiasttoPromise()
, które, jak wskazano tutaj, jest przestarzałe począwszy od RxJS 7 i zostanie usunięte w RxJS 8.Jest to dostępne w RxJS 7+
Zobacz: https://indepth.dev/rxjs-heads-up-topromise-is-being-deprecated/
źródło