【问题标题】:RxSwift map and flatMap differenceRxSwift map 和 flatMap 的区别
【发布时间】:2018-09-12 15:38:28
【问题描述】:

我无法理解 RxSwift 中 map 和 flatMap 之间的区别。在 RxSwift 游乐场示例和书籍中,flatMap 被用作转换具有内部 Observable 属性的 Observables。

但是我看到 flatMap 直接用于基本类型的 Observable。例如对于下面的代码,它们都产生相同的输出。谁能帮我理解 map 和 flatMap 之间的区别

struct Student {
    let score:Int
}

let ryan = Student(score:80)
let student = PublishSubject<Student>()

let deneme = student.map({ val in
    return Student(score: val.score+10)
})
deneme.subscribe(onNext: {
    print("StudentMAP: \($0.score)")
})

let deneme2 = student.flatMap({ val -> Observable<Student> in
    return Observable.of(Student(score: val.score + 10))
})

deneme2.subscribe(onNext: {
    print("StudentFlatMAP: \($0.score)")
})

 student.onNext(ryan)

【问题讨论】:

    标签: swift rx-swift


    【解决方案1】:

    为了简单起见 当你想在流中返回 Observable 时使用 flatMap。 使用 map 只是简单地转换 observable 的值并向下传递流

    平面图:

    response.flatMap { response, _ -> Observable<NSString> in
            guard let value = response.allHeaderFields["string"] as? NSString
                else {
                    return Observable.empty()
            }
    
            return Observable.just(value)
            }.subscribe(onNext: { [weak self]  string in
                print(string)
            }).disposed(by: bag)
    

    地图:

     response.filter { response, _  in
                return 200..<300 ~= response.statusCode
                }.map { _ , data -> [[String: Any]] in
    
                    guard let jsonObject = try? JSONSerialization.jsonObject(with: data, options: []),
                        let result = jsonObject as? [[String: Any]] else {
                            return []
                    }
                    return result
                }.subscribe(onNext: { [weak self] objects in
                    print(objects)
                }).disposed(by: bag)
    

    【讨论】:

      【解决方案2】:

      ma​​p 从流中获取值并返回任何类型的另一个值,结果是 Observable。

      flatMap 从流中获取值并返回任何类型的 Observable

      这意味着您可以在以下情况下使用 flatMap

      • 你已经声明了一个返回 Observable,所以你可能想在 flatMap 中使用它

        func foo(_ number: Int) -> Observable<String> {
            return Observable.just(String(number))
        }
        
        Observable.just(1)
            .flatMap { (number) -> Observable<String> in
                return foo(number)
        }
        
      • 您需要将返回值推送到流中的多个值

        func updates() -> Observable<String> {
            // Something that generates updates
        }
        
        func shouldListenToUpdated() -> Observable<Bool> {
            return Observable.just(true)
        }
        
        shouldListenToUpdated()
            .flatMap { (listenToUpdated) -> Observable<String> in
                return listenToUpdated ? updates() : Observable.empty()
        }
        

      而 map 只会转换流中的下一个值。

      希望这能澄清一点。

      【讨论】:

      【解决方案3】:

      flatMap 类似于 map,但它将可观察的元素转换为可观察的序列。您使用的示例相对简单,它只是将发送和 Observable 映射到其他东西。

      Here 引用自 Reactive 扩展文档,

      FlatMap 运算符通过应用函数来转换 Observable 您为源 Observable 发出的每个项目指定的,其中 该函数返回一个本身发出项目的 Observable。平面图 然后合并这些结果 Observable 的发射,发射 这些合并的结果作为它自己的序列。

      这个方法很有用,例如,当你有一个 Observable 时 发出一系列项目,这些项目本身具有 Observable 成员或 以其他方式可转换为 Observables,这样您就可以创建一个 新的 Observable 发出由发出的项目的完整集合 这些项目的子 Observables。

      如果你稍微扩展一下这个例子,你就会知道 flatMap 实际上将每个元素转换为一个序列。

      注意你用过,

      student.onNext(ryan)
      

      删除您的 dename2 并在下面添加此代码,

      let studentObservable: PublishSubject<Student> = PublishSubject()
      
      let deneme2 = student.flatMap({ val -> Observable<Student> in
          return studentObservable.map { val in Student(score: val.score + 10) }
      })
      
      deneme2.subscribe(onNext: {
          print("StudentFlatMAP: \($0.score)")
      })
      
      student.onNext(ryan)
      
      studentObservable.onNext(Student(score: 80))
      studentObservable.onNext(Student(score: 90))
      studentObservable.onNext(Student(score: 100))
      

      现在,您可以看到 map 将简单地转换序列中的值并创建新的 Observable,而 flatMap 将其转换为序列.现在,每个 flatMapped 元素都可以自己发出值,因为它们本身就是流。

      【讨论】:

      • 您的代码无法编译。 studentObservablestudent 不同吗?您是否使用以前的学生 PublishSubject 和 flatMap 到 studentObservable。我真的不明白。
      • 哪里不编译? studentObservable 是一个新的 PublishSubject,它是为同一个学生干预你的 flatMap 的新序列
      • @Meanteacher 查看更改,您应该删除您的 dename2 并将代码替换为上面的代码。
      • 我更改了顺序,现在它已编译。我还没有完全明白。例如,如果我使用学生发布主题,当我向主题发布新项目时,地图和平面地图都会打印相同的内容。它们都是可观察的我不明白地图和平面地图的可观察物的区别。我将一遍又一遍地阅读您的答案。谢谢。
      猜你喜欢
      • 1970-01-01
      • 2019-12-29
      • 1970-01-01
      • 2019-04-01
      • 2014-12-28
      • 2011-10-05
      • 2018-08-23
      • 2014-04-16
      相关资源
      最近更新 更多