RxSwift map 和 flatMap 的区别

RxSwift map and flatMap difference

我无法理解 RxSwift 中 map 和 flatMap 的区别。在 RxSwift 游乐场示例和书籍中,flatMap 被用作转换具有内部 Observable 属性 的 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: \([=10=].score)")
})

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

deneme2.subscribe(onNext: {
    print("StudentFlatMAP: \([=10=].score)")
})

 student.onNext(ryan)

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

Here 引用自 Reactive 扩展文档,

The FlatMap operator transforms an Observable by applying a function that you specify to each item emitted by the source Observable, where that function returns an Observable that itself emits items. FlatMap then merges the emissions of these resulting Observables, emitting these merged results as its own sequence.

This method is useful, for example, when you have an Observable that emits a series of items that themselves have Observable members or are in other ways transformable into Observables, so that you can create a new Observable that emits the complete collection of items emitted by the sub-Observables of these items.

如果稍微扩展一下示例,您就会知道 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: \([=11=].score)")
})

student.onNext(ryan)

studentObservable.onNext(Student(score: 80))
studentObservable.onNext(Student(score: 90))
studentObservable.onNext(Student(score: 100))

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

map 从流中获取值和 return 任何类型的另一个值,结果是 Observable< whatever type >。

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

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

  • 您已经声明了一个 returns Observable< 的函数? >,所以你可能想在 flatMap

    中使用它
    func foo(_ number: Int) -> Observable<String> {
        return Observable.just(String(number))
    }
    
    Observable.just(1)
        .flatMap { (number) -> Observable<String> in
            return foo(number)
    }
    
  • 您需要 returned 值在流中推送多个值

    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 只会转换流中的下一个值。

希望这能澄清一些事情。

为了简单起见 当你想要 return Observable down the stream 时使用 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)