关于在RxSwift中flatMapLatest的困惑

时间:2016-05-26 08:48:11

标签: swift functional-programming reactive-cocoa rx-swift

我在RxSwift中学习了示例代码。在文件GithubSignupViewModel1.swift中,validatedUsername的定义是:

t2

validateUsername方法最终被称为以下方法:

t1$x3 <- as.character(t1$x3)
t2$x3 <- as.character(t2$x3)
t1[t1$x1 %in% t2$x1 & as.character(t1$x2) %in% as.character(t2$x2), "x3"] <- t2$x3

> t1
#  x1 x2 x3
#1  1  I  a
#2  7  R  a
#3  3  R  a
#4  4  I  b
#5  2  I  b
#6  6  R  b

这是我的困惑:

每当我在用户名文本字段中快速输入字符时,消息--------&gt; 1:,--------&gt; 2:显示,稍后消息--- -----&gt; 3:显示,但只显示了一个--------&gt; 3:消息。

当我输入较慢的字符时,消息--------&gt; 1:,--------&gt; 2:,--------&gt; 3:连续显示。

但是当我将flatMapLatest更改为flatMap时,我输入了多少个字符,我将得到相同数量的--------&gt; 3:message。

那么flatMapLatest如何在这里工作?

flatMapLatest如何过滤NSURLResponse的早期响应?

我读了一些关于flatMapLatest的内容,但没有一个能解释我的困惑。

我看到的是:

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)

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) } 更改为另一个变量时,变量(XX)不会影响a的订阅者。

但是let a = Variable(XX) a.asObservable().flatMapLatest(...) 没有改变,它始终是a.value!那么flatMapLatest如何工作?

4 个答案:

答案 0 :(得分:16)

TheDroidsOnDroid的回答对我来说很清楚:

FlatMapLatest diagram

  

嗯,flatMap()得到一个值,然后执行长任务,然后执行   得到下一个值,前一个任务即使在新的时候仍然会完成   值到达当前任务的中间。这不是真的   我们需要因为当我们在搜索栏中获得新文本时,我们想要   取消上一个请求并启动另一个请求。那是什么   flatMapLatest()可以。

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

您可以在Appstore上使用RxMarbles应用程序来使用运算符。

答案 1 :(得分:14)

目前尚不清楚你的困惑是什么。您是否在质疑flatMapflatMapLatest之间的区别? flatMap会映射到新的Observable,如果需要再次flatMap,它实际上会将两个映射的Observable合并为一个。如果需要再次flatMap,它将再次合并,等等。

使用flatMapLatest时,如果映射了新的Observable,则会覆盖最后一个Observable(如果有)。没有合并。

编辑: 在回复您的评论时,您没有看到任何"------>3:"打印件的原因是因为rx_request Observable在竞争之前已被处置,因为flatMapLatest收到了新的元素,并映射到新的Observable。处置后,rx_request可能取消请求,并且不会在您打印的地方运行回调。旧的Observable被处置掉了,因为当新的var list = ctx.Web.Lists.GetByTitle(listTitle); var items = list.GetItems(CamlQuery.CreateAllItemsQuery()); var result = ctx.LoadQuery(items.Where(i => (bool)i["IsSummary"]).Include(i => i["Name"], i => i["Start"], i => i["Finish"])); ctx.ExecuteQuery(); foreach (var item in result) { Console.WriteLine(item["Name"]); } 取代它时,它不再属于任何人。

答案 2 :(得分:9)

我觉得这个https://github.com/ReactiveX/RxSwift/blob/master/Rx.playground/Pages/Transforming_Operators.xcplaygroundpage/Contents.swift很有用

  

将Observable序列发出的元素转换为Observable序列,并将来自两个Observable序列的发射合并为一个Observable序列。 例如,当您有一个Observable序列本身发出Observable序列,并且您希望能够对来自Observable序列的新发射做出反应时,这也很有用。 flatMap和flatMapLatest之间的区别在于,flatMapLatest只会从最近的内部Observable序列中发出元素。

    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

使用flatMap,我们得到

80
85
90
95
100

使用flatMapLatest,我们得到

80
85
90
100
  

在此示例中,使用flatMap可能会产生意想不到的后果。后   分配给player.value,.score将开始发射   元素,但前面的内部Observable序列(.score)会   还会发出元素。通过将flatMap更改为flatMapLatest,仅限   最新的内部Observable序列(.score)将发出   元素,即将.score.value设置为95无效。

     

flatMapLatest实际上是map和switchLatest的组合   运算符。

另外,我发现https://www.raywenderlich.com/158205/rxswift-transforming-operators这个很有用

flatMap

  

跟上它创建的每个可观察对象,每个元素添加到源可观察对象

flatMapLatest

  

使flatMap最大的不同之处在于它将自动切换到最新的observable并取消订阅前一个。

答案 3 :(得分:3)

我认为来自Ray Wenderlich tutorial的图表可以提供帮助。

flatMapLatest diagram