RxSwift地图和flatMap差异

时间:2018-04-03 10:33:46

标签: swift rx-swift

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

但是我看到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)

3 个答案:

答案 0 :(得分:8)

map 从流中获取值并返回任何类型的其他值,结果为Observable&lt;无论什么类型&gt;。

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

这意味着您可以在:

时使用 flatMap
  • 你已经声明了一个返回Observable&lt;的函数。 ? &gt;,所以你可能想在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只会转换流中的下一个值。

希望这能澄清一些事情。

答案 1 :(得分:1)

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

Here引用了Reactive扩展文档,

  

FlatMap运算符通过应用函数转换Observable   您为源Observable发出的每个项指定的位置   该函数返回一个本身发出项目的Observable。 FlatMap   然后合并这些由此产生的Observables的排放量   这些合并后的结果就是它自己的序列。

     

此方法很有用,例如,当你有一个Observable时   发出一系列本身具有Observable成员的项目   在其他方面可以转换为Observables,以便您可以创建一个   新的Observable,用于发出由其发出的完整项目集合   这些项目的子可观测量。

如果您稍微扩展一下示例,您就会知道 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元素本身都可以发出值,因为它们本身就是流。

答案 2 :(得分:1)

为简单起见 当您想在下游返回Observable时,请使用flatMap。 使用地图只是将可观察对象的值转换并向下传递流

平面图:

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)