Nie wiem, jak wyodrębnić wartość z Observable, aby została zwrócona przez funkcję, w której obecny jest Observable. Potrzebuję tylko wartości z tego, aby została zwrócona, nic więcej.
Aktualna wersja, która działa
function getValueFromObservable() {
this.store.subscribe(
(data:any) => {
console.log(data)
}
)
}
getValueFromObservable()
Potrzebuję tego do działania, funkcji do zwracania wartości, a następnie:
function getValueFromObservable() {
this.store.subscribe(
(data:any) => {
return data
}
)
}
console.log(getValueFromObservable())
Co ja tu robię źle?
typescript
angular
rxjs
rxjs5
Miś
źródło
źródło
subscribe
Odpowiedzi:
EDYCJA: zaktualizowany kod w celu odzwierciedlenia zmian wprowadzonych w sposobie działania rur w nowszych wersjach RXJS. Wszystkie operatory (w moim przykładzie) są teraz opakowane w operator pipe ().
Zdaję sobie sprawę, że to pytanie było dawno temu i na pewno masz już właściwe rozwiązanie, ale dla każdego, kto go szuka, sugerowałbym rozwiązanie go z Obietnicą zachowania wzorca asynchronicznego.
Bardziej szczegółowa wersja stworzyłaby nową obietnicę:
function getValueFromObservable() { return new Promise(resolve=>{ this.store.pipe( take(1) //useful if you need the data once and don't want to manually cancel the subscription again ) .subscribe( (data:any) => { console.log(data); resolve(data); }) }) }
Po stronie odbiorczej będziesz musiał „czekać” na rozwiązanie obietnicy za pomocą czegoś takiego:
getValueFromObservable() .then((data:any)=>{ //... continue with anything depending on "data" after the Promise has resolved })
Węższym rozwiązaniem byłoby użycie .toPromise () RxJS zamiast:
function getValueFromObservable() { return this.store.pipe(take(1)) .toPromise() }
Oczywiście strona odbiorcza pozostaje taka sama jak powyżej.
źródło
getValueFromObservable
funkcji?To nie jest do końca poprawny pomysł użycia
Observable
W komponencie musisz zadeklarować składową klasy, która będzie zawierała obiekt (coś, czego zamierzasz użyć w swoim komponencie)
export class MyComponent { name: string = ""; }
Wtedy
Service
będzie wrócił ciObservable
:getValueFromObservable():Observable<string> { return this.store.map(res => res.json()); }
Component
powinien przygotować się na odzyskanie z niego wartości:OnInit(){ this.yourServiceName.getValueFromObservable() .subscribe(res => this.name = res.name) }
Musisz przypisać wartość z an
Observable
do zmiennej:Twój szablon będzie zużywał zmienną
name
:Innym sposobem użycia
Observable
jest użycieasync
potoku http://briantroncone.com/?p=623Uwaga : jeśli nie o to pytasz, zaktualizuj swoje pytanie, podając więcej szczegółów
źródło
name
poza wywołaniem zwrotnym, przypisując je doname
zmiennej składnika . Wname
twoim przypadku nie ma możliwości powrotu synchronicznego.Oninit
ten sposób, a co jeśli muszę zwrócić jawnie, mój kod wywoławczy wygląda takthis.actions$.ofType(SearchActions.SEARCH_MULTIPLE_NEW_QUERY).map(toPayload).fnWithMultipleAsyncReturns()
Jeśli chcesz wstępnie zasubskrybować to samo Observable, które zostanie zwrócone, po prostu użyj
function getValueFromObservable() { return this.store.do( (data:any) => { console.log("Line 1: " +data); } ); } getValueFromObservable().subscribe( (data:any) => { console.log("Line 2: " +data) } );
źródło
.map(data => data)
który robi to samo, a następnie zasubskrybować go wszędzie tam, gdzie spodziewasz się wynikudo
jest teraz wywoływanytap
i musisz go użyć w potoku. Należy również zauważyć, żetap
przyjmuje wiele parametrów dla różnych programów obsługi, takich jaknext
,complete
ierror
.Wygląda na to, że szukasz elementu pobierającego „wartość bieżącą” wewnątrz obiektu obserwowalnego, kiedy emituje i po emisji.
Subject
iObservable
nie ma czegoś takiego. Kiedy wartość jest emitowana, jest przekazywana jej subskrybentom iObservable
kończy się z nią.Możesz skorzystać z tego,
BehaviorSubject
który przechowuje ostatnią wyemitowaną wartość i natychmiast emituje ją nowym abonentom.Posiada również
getValue()
metodę uzyskiwania bieżącej wartości;Dalsze czytanie:
RxJS BehaviorSubject
Jak uzyskać aktualną wartość przedmiotu RxJS lub obserwowalnego?
źródło
Obserwowalne wartości można pobrać z dowolnej lokalizacji. Sekwencja źródłowa jest najpierw wypychana na specjalnego obserwatora, który może emitować gdzie indziej. Osiąga się to za pomocą klasy Subject z Reactive Extensions (RxJS).
var subject = new Rx.AsyncSubject(); // store-last-value method
Przechowuj wartość dla obserwatora .
subject.next(value); // store value subject.complete(); // publish only when sequence is completed
Aby pobrać wartość z innego miejsca, zasubskrybuj obserwatora w następujący sposób:
subject.subscribe({ next: (response) => { //do stuff. The property name "response" references the value } });
Podmioty są zarówno obserwatorami, jak i obserwatorami. Istnieją inne typy podmiotów, takie jak BehaviourSubject i ReplaySubject dla innych scenariuszy użycia.
Nie zapomnij zaimportować RxJS.
var Rx = require('rxjs');
źródło
Chociaż poprzednie odpowiedzi mogą działać w pewien sposób, myślę, że używanie BehaviorSubject jest właściwym sposobem, jeśli chcesz nadal używać obserwabli.
Przykład:
this.store.subscribe( (data:any) => { myService.myBehaviorSubject.next(data) } )
W serwisie:
let myBehaviorSubject = new BehaviorSubjet(value);
W component.ts:
this.myService.myBehaviorSubject.subscribe(data => this.myData = data)
Mam nadzieję, że to pomoże!
źródło
Na przykład to jest mój szablon HTML:
<select class="custom-select d-block w-100" id="genre" name="genre" [(ngModel)]="film.genre" #genreInput="ngModel" required> <option value="">Choose...</option> <option *ngFor="let genre of genres;" [value]="genre.value">{{genre.name}}</option> </select>
To jest pole, które zostało powiązane z szablonem z mojego komponentu:
// Genres of films like action or drama that will populate dropdown list. genres: Genre[];
Dynamicznie pobieram gatunki filmów z serwera. W celu komunikacji z utworzonym przeze mnie serwerem
FilmService
To jest metoda komunikacji z serwerem:
fetchGenres(): Observable<Genre[]> { return this.client.get(WebUtils.RESOURCE_HOST_API + 'film' + '/genre') as Observable<Genre[]>; }
Dlaczego ta metoda
Observable<Genre[]>
nie zwraca czegoś takiegoGenre[]
?JavaScript jest
async
i nie czeka, aż metoda zwróci wartość po kosztownym procesie. Przez kosztowny mam na myśli proces, który wymaga czasu, aby zwrócić wartość. Podobnie jak pobieranie danych z serwera. Więc trzeba zwrócić odniesienie obserwowalnych i zapisz go.Na przykład w moim komponencie:
ngOnInit() { this.filmService.fetchGenres().subscribe( val => this.genres = val ); }
źródło
function getValueFromObservable() { this.store.subscribe( (data:any) => { return data } ) } console.log(getValueFromObservable())
W powyższym przypadku console.log zostanie uruchomiona, zanim obietnica zostanie rozwiązana, więc żadna wartość nie jest wyświetlana, zmień ją na następującą
function getValueFromObservable() { return this.store } getValueFromObservable() .subscribe((data: any) => { // do something here with data console.log(data); });
innym rozwiązaniem jest, gdy potrzebujesz danych wewnątrz getValueFromObservable, aby zwrócić obserwowalne użycie operatora i zasubskrybować funkcję.
function getValueFromObservable() { return this.store.subscribe((data: any) => { // do something with data here console.log(data); //return again observable. return of(data); }) } getValueFromObservable() .subscribe((data: any) => { // do something here with data console.log(data); });
źródło
W jednowątkowym, asynchronicznym, zorientowanym na obietnice, reaktywnym świecie javascript
async/await
jest najlepszym przyjacielem programisty w stylu imperatywnym:(async()=>{ const store = of("someValue"); function getValueFromObservable () { return store.toPromise(); } console.log(await getValueFromObservable()) })();
A w przypadku, gdy
store
jest to sekwencja wielu wartości:const aiFrom = require('ix/asynciterable').from; (async function() { const store = from(["someValue","someOtherValue"]); function getValuesFromObservable () { return aiFrom(store); } for await (let num of getValuesFromObservable()) { console.log(num); } })();
źródło
from(["someValue","someOtherValue"])
wybraną obserwowalną, która emituje więcej niż jedną wartość. Myślę, że bardziej odpowiednie byłoby użycieinterval(1000)
.Przyzwoitym sposobem byłoby zwrócenie obserwowalnego z funkcji i zasubskrybowanie go tam, gdzie jest to wymagane, ponieważ obserwowalne są leniwe, zaczną emitować wartości tylko wtedy, gdy zostaną zasubskrybowane.
Tutaj mam jeszcze jedno interesujące rozwiązanie oparte na wydarzeniach, z którym początkowo się bawiłem. Poniższy przykład robi to za pomocą modułu „ events ” programu nodejs. Możesz go używać z innymi frameworkami, w których istnieje podobny moduł ( Uwaga : składnia i styl mogą się zmieniać w zależności od używanego modułu).
var from =require("rxjs").from; var map = require("rxjs/operators").map; var EventEmitter = require("events"); function process(event) { from([1,2,3]).pipe( map(val => `The number is:: ${val}`) ).subscribe((data) => { event.emit("Event1", data); //emit value received in subscribe to the "Event1" listener }); } function main() { class Emitter extends EventEmitter{}; var event = new Emitter(); //creating an event event.on("Event1", (data)=>{ //listening to the event of name "Event1" and callback to log returned result console.log(data); //here log, print, play with the data you receive }); process(event); //pass the event to the function which returns observable. } main(); //invoke main function
To tylko przykład pokazujący pomysł, w którym możemy przekazywać dane z różnych miejsc metodą emisji i nasłuchu. Jest to również znane jako kod sterowany zdarzeniami.
źródło