我无法理解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)
flatMap类似于map,但它将observable元素转换为可观察的序列。您使用的示例相对简单,它只是发送和Observable映射到其他东西。
Here引用了Reactive扩展文档,
FlatMap运算符通过将您指定的函数应用于源Observable发出的每个项来转换Observable,其中该函数返回一个本身发出项的Observable。然后FlatMap合并这些生成的Observable的发射,将这些合并的结果作为自己的序列发出。
这个方法很有用,例如,当你有一个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将简单地从sequence转换一个值,并创建新的Observable,而flatMap将其转换为序列。现在,每个flatMapped元素本身都可以发出值,因为它们本身就是流。
map从流中获取值并返回任何类型的另一个值,结果是Observable <whatever type>。
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只会转换流中的下一个值。
希望这能澄清一些事情。
保持简单当您想要在流中返回Observable时使用flatMap。使用map只是转换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)