2016-04-10 4 views
1

ein ähnliches Beispiel Nach 39 hier in Frage: http://reactivex.io/learnrx/RXSwift - takeUntil Cancelling vor dem nächsten Ereignis

Ich versuche, ein Methodenaufruf in eine Folge dieser Anrufe zu transformieren. Sie erreichen dies durch Erstellen einer Variable, die ich mit dem query Wert jedes Mal aktualisieren die Methode aufgerufen wird.

Dann habe ich in meinem init():

_ = queryVariable.asObservable().flatMap({ query -> Observable<[JSON]> in 
    return self.facebookSearch(query).takeUntil(self.queryVariable.asObservable()) 
}).subscribeNext({ result in 
    if let name = result[0]["name"].string { 
     print(name) 
    } else { 
     print("problem") 
    } 
}) 

Wenn ich tippe "ABC", wird meine Methode 3 mal mit "A", "ABC""AB", genannt werden. Das würde seq(["A", "AB", "ABC"]) mit queryVariable.asObservable() zugeordnet werden. Dann mappe ich es auf Facebook-Suchen (Leute auf ihren Namen auf Facebook suchen). Und mit subscribeNext drucke ich den Namen. Wenn ich nicht die takeUntil verwende, funktioniert es wie erwartet, ich bekomme 3 Sätze von Ergebnissen, einen für jede meiner Abfragen ("A", "AB", "ABC").

Aber wenn ich schnell tippe (bevor Facebook Zeit hat, auf die Anfrage zu antworten), würde ich nur ein Ergebnis für die Abfrage wünschen "ABC". Deshalb habe ich die takeUntil hinzugefügt. Damit würde ich erwarten, dass der facebookSearch(query: String) Aufruf ignoriert wird, wenn der nächste query hereinkommt, aber für die aktuelle Abfrage abgebrochen wird, so dass ich mit diesem takeUntil nichts drucke.

Ist dies ein bekanntes Problem oder mache ich etwas falsch?

Antwort

2

verwendete ich Ihren Code und fand zwei Lösungen für Ihr Problem:

1. Verwenden Sie flatMapLatest

Sie können nur flatMapLatest anstelle von flatMap und takeUntil. flatMapLatest gibt nur die Ergebnisse der letzten Suchaufträge storniert alle älteren Anfragen, die noch nicht zurückgekehrt sind:

_ = queryVariable.asObservable() 
    .flatMapLatest { query -> Observable<String> in 
     return self.facebookSearch(query) 
    } 
    .subscribeNext { 
     print($0) 
    } 

2. Verwenden share

Um Ihren Ansatz Arbeit zu machen, müssen Sie die Ereignisse gemeinsam nutzen Ihre queryVariable beobachtbare, wenn Sie es auch für takeUntil verwenden:

let queryObservable = queryVariable.asObservable().share() 

_ = queryObservable 
    .flatMap { query -> Observable<String> in 
     return self.facebookSearch(query).takeUntil(queryObservable) 
    } 
    .subscribeNext { 
     print($0) 
    } 

Wenn Sie die Ereignisse nicht teilen, die searchQuery.asObservable() in takeUntil erstellt seine eigene (doppelte) Sequenz. Wenn dann ein neuer Wert für die Variable searchQuery festgelegt wird, wird sofort ein Next-Ereignis in der takeUntil() - Sequenz ausgelöst und die facebookSearch-Ergebnisse werden abgebrochen.

Wenn Sie share() die Sequenz in takeUntil verwenden wird, um das gleiche Ereignis wie die andere Sequenz zu beobachten und in diesem Fall ist die takeUntil Sequenz behandelt das nächste Ereignis, nachdem die facebookSearch eine Antwort zurückgegeben hat.

IMHO der erste Weg (flatMapLatest) ist der bevorzugte Weg, wie dieses Szenario zu behandeln.

+0

Aber ich annulliere nicht die gesamte Sequenz, ich benutze TakeUntil nur auf dieser bestimmten FacebookSearch. Genau wie Übung 39. Was ist der Unterschied hier? –

+0

Wenn ich statt einer Variable auch PublishSubject verwende, funktioniert die TakeUtil wie ich beschrieben. Aber ich verstehe den Unterschied wirklich nicht. –

+0

OK, ich habe mir Beispiel 39 angesehen. Ich füge den Unterschied zwischen dem Beispiel und Ihrem Code zu der Antwort hinzu. – joern

Verwandte Themen