2016-05-26 10 views
6

Apprendimento del codice di esempio in RxSwift. Nel file GithubSignupViewModel1.swift, la definizione di validatedUsername è:Confusione su 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) 

il metodo validateUsername viene finalmente chiamato il seguente metodo:

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) 
} 

Ecco la mia confusione:

ogni volta che un ingresso carattere rapidamente nel campo di testo username, messaggio --------> 1 :, --------> 2: mostrato, e un messaggio poco successivo --------> 3: mostrato , ma ha mostrato solo uno --------> 3: messaggio.

Quando inserisco i caratteri più lentamente, messaggio --------> 1 :, --------> 2 :, --------> 3: mostrato successivamente.

Ma quando cambio flatMapLatest in flatMap, quanti caratteri immetto, otterrò lo stesso numero di --------> 3: message.

Quindi, come ha funzionato flatMapLatest qui?

In che modo flatMapLatest filtra la risposta anticipata da NSURLResponse?


Ho letto alcuni su flatMapLatest, ma nessuno di loro spiegherà la mia confusione.

Quello che ho visto è qualcosa di simile:

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

Quando cambiato a.value a un'altra variabile, la variabile (XX) non influenzerà l'abbonato di una.

Ma lo input.username non viene modificato, è sempre un testfield.rx_text! Quindi, come funziona flatMapLatest?

risposta

8

Non è chiaro di cosa si tratti. Stai mettendo in dubbio la differenza tra flatMap e flatMapLatest? flatMap eseguirà il mapping su un nuovo Observable e, se necessario, sarà nuovamente necessario per flatMap, in unire i due mappati Observable. Se ha bisogno di flatMap di nuovo, si unirà di nuovo, ecc

Con flatMapLatest, in caso di nuove Observable è mappato, sovrascrive l'ultimo Observable se ci fosse uno. Non c'è unione.

EDIT: In risposta al tuo commento, la ragione per cui non si è visto alcun "------>3:" stampa è perché quelle rx_requestObservable s sono stati eliminati prima che potessero competere, perché flatMapLatest ha ricevuto un nuovo elemento, e questo mappati ad un nuovo Observable . Al momento dello smaltimento, rx_request annulla probabilmente la richiesta e non eseguirà la richiamata su cui si sta stampando. Il vecchio Observable è eliminato perché non appartiene più a nessuno quando il nuovo prende il suo posto.

+0

"input.name" non è stato modificato! C'è solo un 'Osservabile'. La chiusura in flatMapLatest veniva richiamata ogni volta, ma la richiesta di rete veniva restituita solo una volta. – leizh00701

+0

Controlla la modifica. – solidcell

+2

Ho avuto un'altra spiegazione su 'flatMapLatest', e ha risolto la mia confusione. https://github.com/baconjs/bacon.js/wiki/Diagrams. Grazie. – leizh00701

9

risposta di TheDroidsOnDroid è chiaro per me:

FlatMapLatest diagram

Beh, flatMap() ottiene un valore, quindi esegue lungo lavoro, e quando ottiene il valore successivo, compito precedente sarà ancora finire anche quando il nuovo valore arriva nel mezzo dell'attività corrente. Non è proprio quello che ci serve perché quando otteniamo un nuovo testo nella barra di ricerca, vogliamo annullare la richiesta precedente e avviarne un'altra. Questo è ciò che fa flat flat flat flat() da .

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

È possibile utilizzare RxMarbles app su AppStore per giocare con gli operatori.

4

Ho trovato questo https://github.com/ReactiveX/RxSwift/blob/master/Rx.playground/Pages/Transforming_Operators.xcplaygroundpage/Contents.swift sia utile

trasforma gli elementi emessi da una sequenza osservabile in sequenze osservabili, e fonde le emissioni di entrambe le sequenze osservabili in una singola sequenza osservabile. Ciò è utile anche quando, ad esempio, quando si dispone di una sequenza Osservabile che emette se stesso sequenze osservabili, e si desidera essere in grado di reagire alle nuove emissioni dalla sequenza osservabile. La differenza tra flatMap e flatMapLatest è, flatMapLatest emetterà solo elementi dalla sequenza interna osservabile più recente.

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 

Con flatMap, otteniamo

80 
85 
90 
95 
100 

Con flatMapLatest, otteniamo

80 
85 
90 
100 

In questo esempio, utilizzando flatMap può avere conseguenze impreviste. Dopo l'assegnazione di a player.value, .score inizierà a emettere gli elementi , ma la sequenza interna osservabile precedente (.score) sarà anche emettere ancora elementi. Modificando flatMap su flatMapLatest, solo la sequenza interna osservabile più recente (.score) emetterà gli elementi , vale a dire l'impostazione .score.value su 95 non ha alcun effetto.

flatMapLatest è in realtà una combinazione di mappa e switchLatest operatori.

Inoltre, trovo https://www.raywenderlich.com/158205/rxswift-transforming-operators questo per essere utile

flatMap

stia al passo con ogni osservabile crea, uno per ogni elemento aggiunto sulla sorgente osservabile

flatMapLatest

Ciò che rende flatMapLatest diverso è che passerà automaticamente all'ultima osservabile e annullata dalla precedente.