在这里订阅普通类型和可观察类型有什么区别?
What difference does it make to subscribe to a normal type and a observable type in here?
let s = "Hello World"
let string = BehaviorSubject(value: s)
//Example 1
string
.map { _ in "hhh" }
.subscribe(onNext: { element in
print(element)
}, onCompleted: {
print("completed")
}
)
//Example 2
string
.flatMap { s -> Observable<String> in
Observable.just("lll")
}
.subscribe(onNext: { element in
print(element)
}, onCompleted: {
print("completed")
}
)
//Example 3
let aaa = string
.map { _ in "hhh" }
//Example 4
let bbb = string
.flatMap { s -> Observable<String> in
Observable.just("lll")
}
我是 RX 世界的新手,在示例 1 和 2 中,我使用 map
和 flatMap
来测试以测试这种行为。它们之间的主要区别之一是 map
return 普通值类型,而 flatMap
returns Observable 类型。
例3&例4显示aaa
和bbb
的类型都是Observable<String>
..
现在,既然最后它们变成了同一件事,为什么还需要 flatMap
到 return 特定的 Observable
类型?或者为什么你需要 map
到 return 一个 normal value
类型?
(我知道flatMap
可以做其他事情,不属于本次混淆)
map
运算符用于转换值并将转换后的值传递给下一个运算符,其中 flatmap
展平 observables 的层次结构并将其公开为单个运算符
map
和 flatmap
的用例
一般情况下,如果您想转换在当前运算符中收到的值并将其通常同步传递给下一个运算符,则使用 map
。在您的例子中,无论分配给 BehaviorRelay
String
什么值,您都想要 return "hhh" 这是直接的同步值转换,因此 map
有意义
string
.map { _ in "hhh" }
.subscribe(onNext: { element in
print(element)
}, onCompleted: {
print("completed")
}
)
flatmap
用于展平 observable 的层次结构,并将其作为单个 observable 简单地暴露给下一个运算符。示例假设您正在实施搜索,一旦值被触发,您想要进行 API 调用并将响应传递给下一个运算符。现在进行 API 调用是一个异步操作,您知道简单的 map
不会中断,那么您可以使用 flatmap
let string = BehaviorRelay<String>(value: "abcd")
string
.flatMap { s -> Observable<Response> in
return Observable<Response>.create({ (observer) -> Disposable in
//make api call here
//pass data / error using observer.onNext or observer.onError()
return Disposables.create()
})
}
.subscribe(onNext: { element in
print(element)
}, onCompleted: {
print("completed")
}
)
所以这里实际的 API 调用是由 flatMap
运算符内部的 observable 发出的,但对于外部世界,它看起来像 BehaviorRelay 本身将字符串类型的值转换为 Response。
这是完美的,因为不需要知道进行 API 调用所涉及的细节 :)
但说实话,如果你真的要实现搜索,你宁愿选择 flatMapLatest
而不是 flatmap
。阅读有关 flatMap
和 flatMapLatest
的更多信息,以便更好地理解 :)
它们在几个方面有所不同。
map
只为进入其中的每个值发出一个值。而 flatMap
可以为进入其中的每个值发出一个 或更多 个值。
传递给 map 的闭包需要 "pure"(没有副作用)而传递给 flatMap
的闭包可能有副作用(例如磁盘访问,UI 访问和网络访问。)是的,因为 Swift 是一种不纯的语言,您 可以 将副作用放入 map
但这样做会破坏契约。
Sandeep 的回答给出了第二点的例子,下面是第一点的例子:
let string = Observable.of("a", "b", "c")
//Example 1
string
.map { "\([=10=])-x" }
.subscribe(onNext: { element in
print(element) // only prints three values
}, onCompleted: {
print("completed")
}
)
//Example 2
string
.flatMap { Observable.of("\([=10=])-x", "\([=10=])-y", "\([=10=])-z") }
.subscribe(onNext: { element in
print(element) // this prints 9 values.
}, onCompleted: {
print("completed")
}
)
let s = "Hello World"
let string = BehaviorSubject(value: s)
//Example 1
string
.map { _ in "hhh" }
.subscribe(onNext: { element in
print(element)
}, onCompleted: {
print("completed")
}
)
//Example 2
string
.flatMap { s -> Observable<String> in
Observable.just("lll")
}
.subscribe(onNext: { element in
print(element)
}, onCompleted: {
print("completed")
}
)
//Example 3
let aaa = string
.map { _ in "hhh" }
//Example 4
let bbb = string
.flatMap { s -> Observable<String> in
Observable.just("lll")
}
我是 RX 世界的新手,在示例 1 和 2 中,我使用 map
和 flatMap
来测试以测试这种行为。它们之间的主要区别之一是 map
return 普通值类型,而 flatMap
returns Observable 类型。
例3&例4显示aaa
和bbb
的类型都是Observable<String>
..
现在,既然最后它们变成了同一件事,为什么还需要 flatMap
到 return 特定的 Observable
类型?或者为什么你需要 map
到 return 一个 normal value
类型?
(我知道flatMap
可以做其他事情,不属于本次混淆)
map
运算符用于转换值并将转换后的值传递给下一个运算符,其中 flatmap
展平 observables 的层次结构并将其公开为单个运算符
map
和 flatmap
一般情况下,如果您想转换在当前运算符中收到的值并将其通常同步传递给下一个运算符,则使用 map
。在您的例子中,无论分配给 BehaviorRelay
String
什么值,您都想要 return "hhh" 这是直接的同步值转换,因此 map
有意义
string
.map { _ in "hhh" }
.subscribe(onNext: { element in
print(element)
}, onCompleted: {
print("completed")
}
)
flatmap
用于展平 observable 的层次结构,并将其作为单个 observable 简单地暴露给下一个运算符。示例假设您正在实施搜索,一旦值被触发,您想要进行 API 调用并将响应传递给下一个运算符。现在进行 API 调用是一个异步操作,您知道简单的 map
不会中断,那么您可以使用 flatmap
let string = BehaviorRelay<String>(value: "abcd")
string
.flatMap { s -> Observable<Response> in
return Observable<Response>.create({ (observer) -> Disposable in
//make api call here
//pass data / error using observer.onNext or observer.onError()
return Disposables.create()
})
}
.subscribe(onNext: { element in
print(element)
}, onCompleted: {
print("completed")
}
)
所以这里实际的 API 调用是由 flatMap
运算符内部的 observable 发出的,但对于外部世界,它看起来像 BehaviorRelay 本身将字符串类型的值转换为 Response。
这是完美的,因为不需要知道进行 API 调用所涉及的细节 :)
但说实话,如果你真的要实现搜索,你宁愿选择 flatMapLatest
而不是 flatmap
。阅读有关 flatMap
和 flatMapLatest
的更多信息,以便更好地理解 :)
它们在几个方面有所不同。
map
只为进入其中的每个值发出一个值。而flatMap
可以为进入其中的每个值发出一个 或更多 个值。传递给 map 的闭包需要 "pure"(没有副作用)而传递给
flatMap
的闭包可能有副作用(例如磁盘访问,UI 访问和网络访问。)是的,因为 Swift 是一种不纯的语言,您 可以 将副作用放入map
但这样做会破坏契约。
Sandeep 的回答给出了第二点的例子,下面是第一点的例子:
let string = Observable.of("a", "b", "c")
//Example 1
string
.map { "\([=10=])-x" }
.subscribe(onNext: { element in
print(element) // only prints three values
}, onCompleted: {
print("completed")
}
)
//Example 2
string
.flatMap { Observable.of("\([=10=])-x", "\([=10=])-y", "\([=10=])-z") }
.subscribe(onNext: { element in
print(element) // this prints 9 values.
}, onCompleted: {
print("completed")
}
)