首页 文章

RxSwift Map 和flatMap的区别

提问于
浏览
2

我无法理解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)

2 回答

  • 7

    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元素本身都可以发出值,因为它们本身就是流 .

  • 1

    map 从流中获取值并返回任何类型的另一个值,结果是Observable <whatever type> .

    flatMap 从流中获取值和 return an 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只会转换流中的下一个值 .

    希望这能澄清一些事情 .

相关问题