2016-05-26 11 views
6

Uczę się kodu przykładowego w RxSwift. W pliku GithubSignupViewModel1.swift definicja validatedUsername jest:Zamieszanie na temat flatMapLatest w 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) 

metoda validateUsername w końcu nazywa się następującą metodę:

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

Oto mój zamieszanie:

ilekroć wprowadzisz szybko znak w polu tekstowym nazwy użytkownika, wiadomość --------> 1 :, --------> 2: pokazana, a nieco później wiadomość --------> 3: pokazana , ale pokazał tylko jedną --------> 3: wiadomość.

Gdy wprowadzam znaki wolniej, komunikat --------> 1 :, --------> 2 :, --------> 3: wyświetlany kolejno.

Ale kiedy zmienię flatMapLatest na flatMap, ile znaków wprowadzę, otrzymam taką samą liczbę --------> 3: wiadomość.

Jak działał tutaj flatMapLatest?

W jaki sposób flatMapLatest filtruje wczesną odpowiedź z NSURLResponse?


Przeczytałem trochę o flatMapLatest, ale żaden z nich nie wyjaśni mojego zamieszania.

Co widziałem coś takiego jak:

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

Kiedy zmienił a.value do innej zmiennej, zmiennej (XX) nie wpłynie na abonent.

Ale input.username nie jest zmieniany, zawsze jest to testfield.rx_text! Więc jak działa flatMapLatest?

Odpowiedz

8

Nie jest jasne, na czym polega zamieszanie. Czy kwestionujesz różnicę między flatMap a flatMapLatest? flatMap zostanie odwzorowany na nowy Observable, a jeśli będzie potrzebny ponownie flatMap, to w istocie połączy dwie zmapowane Observable s w jedną. Jeśli musi ponownie flatMap będzie go łączyć ponownie itd

Z flatMapLatest, gdy nowy Observable jest odwzorowywany, nadpisuje ostatni Observable jeśli był jeden. Nie ma scalenia.

EDIT: W odpowiedzi na Twój komentarz, z powodu nie są wyświetlane żadne "------>3:" drukiem dlatego te rx_requestObservable s zostały usunięte, zanim będą mogły konkurować, bo flatMapLatest otrzymał nowy element, a to odwzorowane w nowym Observable . Po usunięciu, rx_request prawdopodobnie anuluje żądanie i nie uruchomi wywołania zwrotnego podczas drukowania. Stary Observable został usunięty, ponieważ nie należy już do nikogo, gdy nowy zajmuje jego miejsce.

+0

"nazwa wejściowa" nie została zmieniona! Jest tylko jeden "obserwowalny". Zamknięcie w flatMapLatest wywołane za każdym razem, ale żądanie sieciowe zwrócone tylko raz. – leizh00701

+0

Sprawdź edycję. – solidcell

+2

Mam inne wyjaśnienie na temat 'flatMapLatest', i to rozwiązało moje zamieszanie. https://github.com/baconjs/bacon.js/wiki/Diagrams. Dziękuję Ci. – leizh00701

9

odpowiedź TheDroidsOnDroid jest jasne dla mnie:

FlatMapLatest diagram

No flatMap() pobiera jedną wartość, a następnie wykonuje czasochłonne zadanie, a kiedy dostaje kolejną wartość, poprzednie zadanie będzie jeszcze dokończyć nawet gdy nowa wartość dotrze do środka bieżącego zadania. Nie jest to naprawdę potrzebne, ponieważ gdy otrzymamy nowy tekst na pasku wyszukiwania, chcemy, aby anulować poprzednie żądanie i rozpocząć kolejne. To właśnie robi flatMapLatest().

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

Można użyć RxMarbles app na Appstore się bawić z operatorami.

4

znaleźć to https://github.com/ReactiveX/RxSwift/blob/master/Rx.playground/Pages/Transforming_Operators.xcplaygroundpage/Contents.swift użyteczne

transformuje elementy emitowanego przez obserwowalnych sekwencji do sekwencji obserwowalnych i łączy emisji z obu obserwowalnych sekwencji do pojedynczej sekwencji obserwowalnych. Jest to przydatne również wtedy, gdy na przykład dostępna jest sekwencja obserwowalna, która sama emituje obserwowalne sekwencje, i chcesz mieć możliwość reagowania na nowe emisje z obserwowalnej sekwencji. Różnica między flatMap i flatMapLatest polega na tym, że flatMapLatest emituje tylko elementy z najnowszej wewnętrznej obserwowalnej sekwencji.

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 

Z flatMap otrzymujemy

80 
85 
90 
95 
100 

Z flatMapLatest, otrzymujemy

80 
85 
90 
100 

W tym przykładzie, stosując flatMap może mieć niezamierzone konsekwencje. Po przypisaniu do player.value, .score zacznie emitować elementy , ale poprzednia wewnętrzna obserwowalna sekwencja (.score) będzie także również nadal emitować elementy. Zmieniając flatMap na flatMapLatest, tylko najnowsza wewnętrzna obserwowalna sekwencja (.score) będzie emitować elementy , tj. Ustawienie .score.value na 95 nie daje żadnego efektu.

flatMapLatest jest w rzeczywistości kombinacją operatorów map i switchLatest .

Również uważam https://www.raywenderlich.com/158205/rxswift-transforming-operators to być użyteczne

flatMap

utrzymuje się z każdym obserwowalne tworzy, po jednym dla każdego elementu dodane do źródła obserwowalnego

flatMapLatest

Co wyróżnia platformę flatMapLatest, oznacza, że ​​automatycznie przełącza się ona na ostatnią obserwowalną i anuluje subskrypcję poprzedniej.