javascript - Rxjs toPromise-beteende annorlunda än observable
Jag har ett enkelt exempel där två metoder skapar och returnerar ett löfte. Den andra metoden buildRedCar() anropar den första metoden buildCar(), ändrar värdet som returneras av löftet och returnerar ett annat löfte från sig själv. Koden anropar sedan buildRedCar() och skriver bara ut resultatet i konsolen. Detta fungerar inte när man konverterar till löften, men det fungerar när man använder vanliga observables.
Fungerar inte:
import * as Rx from 'rx';
function buildCar(): Rx.IPromise<string> {
let car = 'Car';
return Rx.Observable.just<string>(car).toPromise();
}
function buildRedCar(): Rx.IPromise<string> {
let observable = Rx.Observable.create<string>((observer) => {
buildCar().then((car) => {
observer.onNext('Red ' + car);
});
})
return observable.toPromise();
}
buildRedCar().then((car) => {
console.log(car);
});
Fungerar:
import * as Rx from 'rx';
function buildCar(): Rx.Observable<string> {
let car = 'Car';
return Rx.Observable.just<string>(car);
}
function buildRedCar(): Rx.Observable<string> {
let observable = Rx.Observable.create<string>((observer) => {
buildCar().subscribe((car) => {
observer.onNext('Red ' + car);
});
})
return observable;
}
buildRedCar().subscribe((car) => {
console.log(car);
});
Någon idé varför beteendet är annorlunda när den enda skillnaden är att konvertera den observerbara till ett löfte innan den returneras?
Svar #1
När RxJs konverterar ett Observable till ett Promise skapar det ett Promise som kommer att ge det sista värdet från observablen. Därför kommer promise inte att lösas förrän den underliggande observablen är klar.
I ditt första exempel (och även i ditt andra), fullbordar du aldrig den röda bil-observable. Därför löses aldrig löftet. Därför producerar aldrig observable som omsluter löftet ett värde...
Ditt andra exempel fungerar eftersom prenumerationen ivrigt skriver ut det första värdet som produceras av din röda bil-oberverbar när det anländer, och sedan "väntar" på ytterligare resultat som aldrig kommer.
Att lägga till ett anrop till onComplete bör få din första version att fungera:
observer.onNext('Red ' + car);
observer.onComplete();
