2016-05-26 12 views
6

Ich lerne den Beispielcode in RxSwift. In der Datei GithubSignupViewModel1.swift ist die Definition von validatedUsername:Verwirrung über flatMapLatest in RxSwift

validatedUsername = input.username //the username is a textfiled.rx_text 
    .flatMapLatest { username -> Observable<ValidationResult> in 
     print("-------->1:") 
     return validationService.validateUsername(username) 
      .observeOn(MainScheduler.instance) 
      .catchErrorJustReturn(.Failed(message: "Error contacting server")) 
    } 
    .shareReplay(1) 

die validateUsername Verfahren schließlich wird die folgende Methode genannt:

func usernameAvailable(username: String) -> Observable<Bool> { 
    // this is ofc just mock, but good enough 
    print("-------->2:") 
    let URL = NSURL(string: "https://github.com/\(username.URLEscaped)")! 
    let request = NSURLRequest(URL: URL) 
    return self.URLSession.rx_response(request) 
     .map { (maybeData, response) in 
      print("-------->3:") 
      return response.statusCode == 404 
     } 
     .catchErrorJustReturn(false) 
} 

Hier ist meine Verwirrung:

wenn ich Eingang ein Zeichen schnell in den Benutzernamen Textfeld, Nachricht --------> 1 :, --------> 2: zeigte, und etwas später Nachricht --------> 3: zeigte , aber zeigte nur eine --------> 3: Nachricht.

Wenn ich Zeichen langsamer eingegeben habe, wurde die Nachricht --------> 1 :, --------> 2 :, --------> 3: nacheinander angezeigt.

Aber wenn ich die FlatMapLatest in FlatMap ändern, wie viele Zeichen ich eingegeben habe, bekomme ich die gleiche Anzahl von --------> 3: Nachricht.

Wie funktioniert der flatMapLatest hier?

Wie die FlatMapLatest die frühe Antwort von NSURLResponse filtern?


Ich lese etwas über die FlatMapLatest, aber keiner von ihnen wird meine Verwirrung erklären.

Was ich sah, ist so etwas wie:

let a = Variable(XX) 
a.asObservable().flatMapLatest(...) 

Wenn a.value auf eine andere Variable verändert, die Variable (XX) nicht dem Teilnehmer ein beeinflussen. Die input.username wird nicht geändert, es ist immer eine testfield.rx_text! Wie funktioniert das flatMapLatest?

Antwort

8

Es ist nicht klar, worum es bei Ihrer Verwirrung geht. Fragen Sie den Unterschied zwischen flatMap und flatMapLatest? flatMap wird zu einem neuen Observable zugeordnet, und wenn es erneut flatMap benötigt, wird es im Wesentlichen die beiden gemappten Observable s in eins zusammenführen. Wenn es wieder flatMap braucht, wird es wieder zusammenführen, usw.

Mit flatMapLatest, wenn ein neuer Observable abgebildet wird, ist es die letzte Observable überschreibt, wenn es eine war. Es gibt keine Zusammenführung.

EDIT: Als Antwort auf Ihren Kommentar, der Grund, warum Sie keine "------>3:" Druck sehen, ist, weil diese rx_requestObservable s angeordnet wurden, bevor sie konkurrieren konnten, weil flatMapLatest ein neues Element empfangen wird, und dies zu einem neuen Observable abgebildet . Nach dem Löschen bricht die rx_request die Anfrage wahrscheinlich ab und führt den Rückruf nicht aus, an dem Sie drucken. Das alte Observable ist entsorgt, weil es niemandem mehr gehört, wenn das neue an seine Stelle tritt.

+0

der 'input.name' wird nicht geändert! Es gibt nur ein "Observable". Die Schließung in flatMapLatest jedes Mal aufgerufen, aber die Netzwerkanforderung nur einmal zurückgegeben. – leizh00701

+0

Überprüfen Sie die Bearbeitung. – solidcell

+2

Ich habe eine andere Erklärung über 'flatMapLatest' bekommen, und es hat meine Verwirrung gelöst. https://github.com/baconjs/bacon.js/wiki/Diagramme. Vielen Dank. – leizh00701

9

TheDroidsOnDroid Antwort ist für mich klar:

FlatMapLatest diagram

Nun, flatMap() wird ein Wert, dann lange Aufgabe ausführt, und wenn es den nächsten Wert bekommt, wird vorherige Aufgabe noch beenden selbst wenn der neue Wert mitten in der aktuellen Aufgabe eintrifft. Es ist nicht wirklich was wir brauchen, denn wenn wir einen neuen Text in der Suchleiste bekommen, wollen wir die vorherige Anfrage abbrechen und eine andere starten. Das ist, was FlatMapLatest() tut.

http://www.thedroidsonroids.com/blog/ios/rxswift-examples-3-networking/

können Sie verwenden RxMarbles App im Appstore mit den Betreibern zu spielen, um.

4

finde ich https://github.com/ReactiveX/RxSwift/blob/master/Rx.playground/Pages/Transforming_Operators.xcplaygroundpage/Contents.swift als nützlich

transformiert die durch eine beobachtbare Sequenz in beobachtbare Sequenzen emittierten Elemente, und führt die Emissionen von sowohl Observable Sequenzen zu einer einzigen Sequenz Observable. Dies ist auch nützlich, wenn Sie zum Beispiel eine beobachtbare Sequenz haben, die selbst beobachtbare Sequenzen aussendet und auf neue Emissionen von entweder der beobachtbaren Sequenz reagieren möchten. Der Unterschied zwischen flatMap und flatMapLatest besteht darin, dass flatMapLatest nur Elemente aus der letzten inneren Observable-Sequenz ausgibt.

let disposeBag = DisposeBag() 

    struct Player { 
     var score: Variable<Int> 
    } 

    let = Player(score: Variable(80)) 
    let = Player(score: Variable(90)) 

    let player = Variable() 

    player.asObservable() 
     .flatMap { $0.score.asObservable() } // Change flatMap to flatMapLatest and observe change in printed output 
     .subscribe(onNext: { print($0) }) 
     .disposed(by: disposeBag) 

    .score.value = 85 

    player.value = 

    .score.value = 95 // Will be printed when using flatMap, but will not be printed when using flatMapLatest 

    .score.value = 100 

Mit flatMap wir

80 
85 
90 
95 
100 

Mit flatMapLatest bekommen, bekommen wir

80 
85 
90 
100 

In diesem Beispiel flatMap mit unbeabsichtigten Folgen haben kann. Nach Zuweisung zu player.value, .score wird beginnen, Elemente zu emittieren, aber die vorherige innere Observable-Sequenz (.score) wird auch weiterhin Elemente emittieren . Durch das Ändern von flatMap in flatMapLatest gibt nur die letzte innere beobachtbare Sequenz (.score) Elemente aus, d. H. Das Setzen von .score.value auf 95 hat keine Auswirkung.

flatMapLatest ist eigentlich eine Kombination der Karte und switchLatest Betreiber.

Auch finde ich https://www.raywenderlich.com/158205/rxswift-transforming-operators diese

flatMap

Schritt hält mit jedem beobachtbaren es schafft, eine für jedes Element, das hinzugefügt werden auf die Quelle beobachtbaren

flatMapLatest

Was unterscheidet flatMapLatest ist, dass es automatisch zu den neuesten beobachtbaren und abmeldet von der vorherigen wechseln wird.