Single.swift 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. //
  2. // Single.swift
  3. // RxSwift
  4. //
  5. // Created by sergdort on 19/08/2017.
  6. // Copyright © 2017 Krunoslav Zaher. All rights reserved.
  7. //
  8. #if DEBUG
  9. import Foundation
  10. #endif
  11. /// Sequence containing exactly 1 element
  12. public enum SingleTrait { }
  13. /// Represents a push style sequence containing 1 element.
  14. public typealias Single<Element> = PrimitiveSequence<SingleTrait, Element>
  15. public enum SingleEvent<Element> {
  16. /// One and only sequence element is produced. (underlying observable sequence emits: `.next(Element)`, `.completed`)
  17. case success(Element)
  18. /// Sequence terminated with an error. (underlying observable sequence emits: `.error(Error)`)
  19. case error(Swift.Error)
  20. }
  21. extension PrimitiveSequenceType where Trait == SingleTrait {
  22. public typealias SingleObserver = (SingleEvent<Element>) -> Void
  23. /**
  24. Creates an observable sequence from a specified subscribe method implementation.
  25. - seealso: [create operator on reactivex.io](http://reactivex.io/documentation/operators/create.html)
  26. - parameter subscribe: Implementation of the resulting observable sequence's `subscribe` method.
  27. - returns: The observable sequence with the specified implementation for the `subscribe` method.
  28. */
  29. public static func create(subscribe: @escaping (@escaping SingleObserver) -> Disposable) -> Single<Element> {
  30. let source = Observable<Element>.create { observer in
  31. return subscribe { event in
  32. switch event {
  33. case .success(let element):
  34. observer.on(.next(element))
  35. observer.on(.completed)
  36. case .error(let error):
  37. observer.on(.error(error))
  38. }
  39. }
  40. }
  41. return PrimitiveSequence(raw: source)
  42. }
  43. /**
  44. Subscribes `observer` to receive events for this sequence.
  45. - returns: Subscription for `observer` that can be used to cancel production of sequence elements and free resources.
  46. */
  47. public func subscribe(_ observer: @escaping (SingleEvent<Element>) -> Void) -> Disposable {
  48. var stopped = false
  49. return self.primitiveSequence.asObservable().subscribe { event in
  50. if stopped { return }
  51. stopped = true
  52. switch event {
  53. case .next(let element):
  54. observer(.success(element))
  55. case .error(let error):
  56. observer(.error(error))
  57. case .completed:
  58. rxFatalErrorInDebug("Singles can't emit a completion event")
  59. }
  60. }
  61. }
  62. /**
  63. Subscribes a success handler, and an error handler for this sequence.
  64. - parameter onSuccess: Action to invoke for each element in the observable sequence.
  65. - parameter onError: Action to invoke upon errored termination of the observable sequence.
  66. - returns: Subscription object used to unsubscribe from the observable sequence.
  67. */
  68. public func subscribe(onSuccess: ((Element) -> Void)? = nil, onError: ((Swift.Error) -> Void)? = nil) -> Disposable {
  69. #if DEBUG
  70. let callStack = Hooks.recordCallStackOnError ? Thread.callStackSymbols : []
  71. #else
  72. let callStack = [String]()
  73. #endif
  74. return self.primitiveSequence.subscribe { event in
  75. switch event {
  76. case .success(let element):
  77. onSuccess?(element)
  78. case .error(let error):
  79. if let onError = onError {
  80. onError(error)
  81. } else {
  82. Hooks.defaultErrorHandler(callStack, error)
  83. }
  84. }
  85. }
  86. }
  87. }
  88. extension PrimitiveSequenceType where Trait == SingleTrait {
  89. /**
  90. Returns an observable sequence that contains a single element.
  91. - seealso: [just operator on reactivex.io](http://reactivex.io/documentation/operators/just.html)
  92. - parameter element: Single element in the resulting observable sequence.
  93. - returns: An observable sequence containing the single specified element.
  94. */
  95. public static func just(_ element: Element) -> Single<Element> {
  96. return Single(raw: Observable.just(element))
  97. }
  98. /**
  99. Returns an observable sequence that contains a single element.
  100. - seealso: [just operator on reactivex.io](http://reactivex.io/documentation/operators/just.html)
  101. - parameter element: Single element in the resulting observable sequence.
  102. - parameter scheduler: Scheduler to send the single element on.
  103. - returns: An observable sequence containing the single specified element.
  104. */
  105. public static func just(_ element: Element, scheduler: ImmediateSchedulerType) -> Single<Element> {
  106. return Single(raw: Observable.just(element, scheduler: scheduler))
  107. }
  108. /**
  109. Returns an observable sequence that terminates with an `error`.
  110. - seealso: [throw operator on reactivex.io](http://reactivex.io/documentation/operators/empty-never-throw.html)
  111. - returns: The observable sequence that terminates with specified error.
  112. */
  113. public static func error(_ error: Swift.Error) -> Single<Element> {
  114. return PrimitiveSequence(raw: Observable.error(error))
  115. }
  116. /**
  117. Returns a non-terminating observable sequence, which can be used to denote an infinite duration.
  118. - seealso: [never operator on reactivex.io](http://reactivex.io/documentation/operators/empty-never-throw.html)
  119. - returns: An observable sequence whose observers will never get called.
  120. */
  121. public static func never() -> Single<Element> {
  122. return PrimitiveSequence(raw: Observable.never())
  123. }
  124. }
  125. extension PrimitiveSequenceType where Trait == SingleTrait {
  126. /**
  127. Invokes an action for each event in the observable sequence, and propagates all observer messages through the result sequence.
  128. - seealso: [do operator on reactivex.io](http://reactivex.io/documentation/operators/do.html)
  129. - parameter onSuccess: Action to invoke for each element in the observable sequence.
  130. - parameter afterSuccess: Action to invoke for each element after the observable has passed an onNext event along to its downstream.
  131. - parameter onError: Action to invoke upon errored termination of the observable sequence.
  132. - parameter afterError: Action to invoke after errored termination of the observable sequence.
  133. - parameter onSubscribe: Action to invoke before subscribing to source observable sequence.
  134. - parameter onSubscribed: Action to invoke after subscribing to source observable sequence.
  135. - parameter onDispose: Action to invoke after subscription to source observable has been disposed for any reason. It can be either because sequence terminates for some reason or observer subscription being disposed.
  136. - returns: The source sequence with the side-effecting behavior applied.
  137. */
  138. public func `do`(onSuccess: ((Element) throws -> Void)? = nil,
  139. afterSuccess: ((Element) throws -> Void)? = nil,
  140. onError: ((Swift.Error) throws -> Void)? = nil,
  141. afterError: ((Swift.Error) throws -> Void)? = nil,
  142. onSubscribe: (() -> Void)? = nil,
  143. onSubscribed: (() -> Void)? = nil,
  144. onDispose: (() -> Void)? = nil)
  145. -> Single<Element> {
  146. return Single(raw: self.primitiveSequence.source.do(
  147. onNext: onSuccess,
  148. afterNext: afterSuccess,
  149. onError: onError,
  150. afterError: afterError,
  151. onSubscribe: onSubscribe,
  152. onSubscribed: onSubscribed,
  153. onDispose: onDispose)
  154. )
  155. }
  156. /**
  157. Filters the elements of an observable sequence based on a predicate.
  158. - seealso: [filter operator on reactivex.io](http://reactivex.io/documentation/operators/filter.html)
  159. - parameter predicate: A function to test each source element for a condition.
  160. - returns: An observable sequence that contains elements from the input sequence that satisfy the condition.
  161. */
  162. public func filter(_ predicate: @escaping (Element) throws -> Bool)
  163. -> Maybe<Element> {
  164. return Maybe(raw: self.primitiveSequence.source.filter(predicate))
  165. }
  166. /**
  167. Projects each element of an observable sequence into a new form.
  168. - seealso: [map operator on reactivex.io](http://reactivex.io/documentation/operators/map.html)
  169. - parameter transform: A transform function to apply to each source element.
  170. - returns: An observable sequence whose elements are the result of invoking the transform function on each element of source.
  171. */
  172. public func map<Result>(_ transform: @escaping (Element) throws -> Result)
  173. -> Single<Result> {
  174. return Single(raw: self.primitiveSequence.source.map(transform))
  175. }
  176. /**
  177. Projects each element of an observable sequence into an optional form and filters all optional results.
  178. - parameter transform: A transform function to apply to each source element.
  179. - returns: An observable sequence whose elements are the result of filtering the transform function for each element of the source.
  180. */
  181. public func compactMap<Result>(_ transform: @escaping (Element) throws -> Result?)
  182. -> Maybe<Result> {
  183. return Maybe(raw: self.primitiveSequence.source.compactMap(transform))
  184. }
  185. /**
  186. Projects each element of an observable sequence to an observable sequence and merges the resulting observable sequences into one observable sequence.
  187. - seealso: [flatMap operator on reactivex.io](http://reactivex.io/documentation/operators/flatmap.html)
  188. - parameter selector: A transform function to apply to each element.
  189. - returns: An observable sequence whose elements are the result of invoking the one-to-many transform function on each element of the input sequence.
  190. */
  191. public func flatMap<Result>(_ selector: @escaping (Element) throws -> Single<Result>)
  192. -> Single<Result> {
  193. return Single<Result>(raw: self.primitiveSequence.source.flatMap(selector))
  194. }
  195. /**
  196. Projects each element of an observable sequence to an observable sequence and merges the resulting observable sequences into one observable sequence.
  197. - seealso: [flatMap operator on reactivex.io](http://reactivex.io/documentation/operators/flatmap.html)
  198. - parameter selector: A transform function to apply to each element.
  199. - returns: An observable sequence whose elements are the result of invoking the one-to-many transform function on each element of the input sequence.
  200. */
  201. public func flatMapMaybe<Result>(_ selector: @escaping (Element) throws -> Maybe<Result>)
  202. -> Maybe<Result> {
  203. return Maybe<Result>(raw: self.primitiveSequence.source.flatMap(selector))
  204. }
  205. /**
  206. Projects each element of an observable sequence to an observable sequence and merges the resulting observable sequences into one observable sequence.
  207. - seealso: [flatMap operator on reactivex.io](http://reactivex.io/documentation/operators/flatmap.html)
  208. - parameter selector: A transform function to apply to each element.
  209. - returns: An observable sequence whose elements are the result of invoking the one-to-many transform function on each element of the input sequence.
  210. */
  211. public func flatMapCompletable(_ selector: @escaping (Element) throws -> Completable)
  212. -> Completable {
  213. return Completable(raw: self.primitiveSequence.source.flatMap(selector))
  214. }
  215. /**
  216. Merges the specified observable sequences into one observable sequence by using the selector function whenever all of the observable sequences have produced an element at a corresponding index.
  217. - parameter resultSelector: Function to invoke for each series of elements at corresponding indexes in the sources.
  218. - returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function.
  219. */
  220. public static func zip<Collection: Swift.Collection, Result>(_ collection: Collection, resultSelector: @escaping ([Element]) throws -> Result) -> PrimitiveSequence<Trait, Result> where Collection.Element == PrimitiveSequence<Trait, Element> {
  221. if collection.isEmpty {
  222. return PrimitiveSequence<Trait, Result>.deferred {
  223. return PrimitiveSequence<Trait, Result>(raw: .just(try resultSelector([])))
  224. }
  225. }
  226. let raw = Observable.zip(collection.map { $0.asObservable() }, resultSelector: resultSelector)
  227. return PrimitiveSequence<Trait, Result>(raw: raw)
  228. }
  229. /**
  230. Merges the specified observable sequences into one observable sequence all of the observable sequences have produced an element at a corresponding index.
  231. - returns: An observable sequence containing the result of combining elements of the sources.
  232. */
  233. public static func zip<Collection: Swift.Collection>(_ collection: Collection) -> PrimitiveSequence<Trait, [Element]> where Collection.Element == PrimitiveSequence<Trait, Element> {
  234. if collection.isEmpty {
  235. return PrimitiveSequence<Trait, [Element]>(raw: .just([]))
  236. }
  237. let raw = Observable.zip(collection.map { $0.asObservable() })
  238. return PrimitiveSequence(raw: raw)
  239. }
  240. /**
  241. Continues an observable sequence that is terminated by an error with a single element.
  242. - seealso: [catch operator on reactivex.io](http://reactivex.io/documentation/operators/catch.html)
  243. - parameter element: Last element in an observable sequence in case error occurs.
  244. - returns: An observable sequence containing the source sequence's elements, followed by the `element` in case an error occurred.
  245. */
  246. public func catchErrorJustReturn(_ element: Element)
  247. -> PrimitiveSequence<Trait, Element> {
  248. return PrimitiveSequence(raw: self.primitiveSequence.source.catchErrorJustReturn(element))
  249. }
  250. /// Converts `self` to `Maybe` trait.
  251. ///
  252. /// - returns: Maybe trait that represents `self`.
  253. public func asMaybe() -> Maybe<Element> {
  254. return Maybe(raw: self.primitiveSequence.source)
  255. }
  256. /// Converts `self` to `Completable` trait.
  257. ///
  258. /// - returns: Completable trait that represents `self`.
  259. public func asCompletable() -> Completable {
  260. return self.primitiveSequence.source.ignoreElements()
  261. }
  262. }