Какая разница между 'bind (onNext:' и 'subscribe (onNext:'?
Если мы проверим реализацию bind(...)
, мы обнаружим, что она ничего не делает, а просто использует subscribe(...)
underhood и вылетает в Debug при ошибке:
/**
Subscribes an element handler to an observable sequence.
In case error occurs in debug mode, `fatalError` will be raised.
In case error occurs in release mode, `error` will be logged.
- parameter onNext: Action to invoke for each element in the observable sequence.
- returns: Subscription object used to unsubscribe from the observable sequence.
*/
public func bind(onNext: @escaping (E) -> Void) -> Disposable {
return subscribe(onNext: onNext, onError: { error in
rxFatalErrorInDebug("Binding error: \(error)")
})
}
Используя bind(onNext)
, вы можете указать, что поток никогда не должен выдавать ошибку и вас интересуют только события элемента.
Таким образом, вы должны использовать subscribe(onNext:...)
, когда вас интересуют события ошибки / завершения / удаления, и bind(onNext...)
в противном случае. Но поскольку он является частью RxCocoa
, а не RxSwift
, я обычно использую subscribe
везде.
a не имеет asObservable (), но хорошо исполняемый. В чем разница а и б?
map(...)
- функция, объявленная в ObservableType
и возвращающая новый Observable
Начнем с ObservableType
.
ObservableType
- это протокол, который требует только одного метода: subscribe(...)
, это позволяет ему создавать реализацию по умолчанию func asObservable()
.
Для вас это означает, что вы можете создать Observable
из любого типа, соответствующего ObservableType
.
/// Represents a push style sequence.
public protocol ObservableType : ObservableConvertibleType {
func subscribe<O: ObserverType>(_ observer: O) -> Disposable where O.E == E
}
extension ObservableType {
/// Default implementation of converting `ObservableType` to `Observable`.
public func asObservable() -> Observable<E> {
// temporary workaround
//return Observable.create(subscribe: self.subscribe)
return Observable.create { o in
return self.subscribe(o)
}
}
}
Таким образом, каждый раз, когда вы вызываете asObservable()
underhood, RxSwift просто создает новую оболочку Observable
вокруг вашего потока.
И если вы проверите источник BehaviourRelay
, то обнаружите, что он также соответствует ObservableType
. Таким образом, вы можете создать Observable
из него в любое время:
public final class BehaviorRelay<Element>: ObservableType { ... }
Теперь давайте проверим map
функцию:
extension ObservableType {
/**
Projects each element of an observable sequence into a new form.
- seealso: [map operator on reactivex.io](http://reactivex.io/documentation/operators/map.html)
- parameter transform: A transform function to apply to each source element.
- returns: An observable sequence whose elements are the result of invoking the transform function on each element of source.
*/
public func map<R>(_ transform: @escaping (E) throws -> R)
-> Observable<R> {
return self.asObservable().composeMap(transform)
}
}
Как и ожидалось map
просто позвоните asObservable()
внутрь и работайте на новом Observable
.
Если мы «развернем» map
, мы получим:
var osInfoA: Observable<String> {
return infoData
.asObservable()
.composeMap { $0.data }
.distinctUntilChanged()
}
var osInfoB: Observable<String> {
return infoData
.asObservable()
.asObservable()
.composeMap { $0.data }
.distinctUntilChanged()
}
Конечно, он не скомпилируется, поскольку composeMap
является внутренней функцией, но у вас есть основная идея.
Вызов asObservable
до того, как другие операторы являются избыточными (большинство операторов определены в ObservableType
) и просто добавляет небольшие накладные расходы.