# monix/monix

Fetching contributors…
Cannot retrieve contributors at this time
5580 lines (5225 sloc) 217 KB
* stream1: 1 - - 2 - - 3 - 4 - -
* stream2: 1 - - 2 - 3 - - - - 4
*
* result: (1, 1), (2, 2), (2, 3), (3, 3), (4, 3), (4, 4)
*
* * See [[zip]] for an alternative that pairs the items in strict sequence. * * @param other is an observable that gets paired with the source */ final def combineLatest[B](other: Observable[B]): Observable[(A, B)] = new CombineLatest2Observable[A, B, (A, B)](self, other)((a, b) => (a, b)) /** Creates a new observable from the source and another given * observable, by emitting elements combined in pairs. * * It emits an item whenever any of the source Observables emits an * item (so long as each of the source Observables has emitted at * least one item). * * == Visual Example == * *
* stream1: 1 - - 2 - - 3 - 4 - -
* stream2: 1 - - 2 - 3 - - - - 4
*
* result: (1, 1), (2, 2), (2, 3), (3, 3), (4, 3), (4, 4)
*
* streamA: a1 -- -- a2 -- -- a3 -- a4 -- --
* streamB: b1 -- -- b2 -- b3 -- -- -- -- b4
*
* result: a1, a2, a3, a4, b1, b2, b3, b4
*
* */ final def ++[B >: A](other: => Observable[B]): Observable[B] = appendAll(Observable.defer(other)) /** * A strict variant of [[++]]. */ final def appendAll[B >: A](other: Observable[B]): Observable[B] = new ConcatObservable[B](self, other) /** Emits the given exception instead of `onComplete`. * * @param error the exception to emit onComplete * @return a new Observable that emits an exception onComplete */ final def endWithError(error: Throwable): Observable[A] = self.liftByOperator(new EndWithErrorOperator[A](error)) /** Returns an observable that emits a single Throwable, in case an * error was thrown by the source, otherwise it isn't going to emit * anything. */ final def failed: Observable[Throwable] = self.liftByOperator(FailedOperator) /** Alias for [[headOrElse]]. */ final def firstOrElse[B >: A](default: => B): Observable[B] = headOrElse(default) /** Emits the first element emitted by the source, or otherwise if the * source is completed without emitting anything, then the * `default` is emitted. */ final def headOrElse[B >: A](default: => B): Observable[B] = head.foldLeft(Option.empty[B])((_, elem) => Some(elem)).map { case Some(elem) => elem case None => default } /** Returns a new observable that applies the given function * to each item emitted by the source and emits the result. */ final def map[B](f: A => B): Observable[B] = self.liftByOperator(new MapOperator(f)) /** Alias for [[concatMap]]. * * NOTE: one primary difference between Monix and other Rx / * ReactiveX implementations is that in Monix `flatMap` is an alias * for `concatMap` and NOT `mergeMap`. */ final def flatMap[B](f: A => Observable[B]): Observable[B] = self.concatMap(f) /** Applies a function that you supply to each item emitted by the * source observable, where that function returns observables, and * then concatenating those resulting sequences and emitting the * results of this concatenation. * * This implements the lawful "monadic bind", the `flatMap` * operation of [[cats.Monad]]. * * ==Example== * {{{ * Observable(1, 2, 3).concatMap { x => * for { * _ <- Observable.eval(println(s"Processing \$\$x")) * x <- Observable(x, x) * } yield x * } * }}} * * \$concatMergeDifference * * @param f is a generator for the streams being concatenated * @return \$concatReturn */ final def concatMap[B](f: A => Observable[B]): Observable[B] = new ConcatMapObservable[A, B](self, f, null, delayErrors = false) /** Alias of [[concatMapDelayErrors]]. */ final def flatMapDelayErrors[B](f: A => Observable[B]): Observable[B] = concatMapDelayErrors(f) /** Alias of [[switchMap]]. */ final def flatMapLatest[B](f: A => Observable[B]): Observable[B] = self.switchMap(f) /** Applies a binary operator to a start value and to elements * produced by the source observable, going from left to right, * producing and concatenating observables along the way. * * It's the combination between [[scan]] and [[flatMap]]. * * @see [[flatScan0]] for the version that emits seed element at the beginning */ final def flatScan[R](seed: => R)(op: (R, A) => Observable[R]): Observable[R] = new FlatScanObservable[A, R](self, seed _, op, delayErrors = false) /** Applies a binary operator to a start value and to elements * produced by the source observable, going from left to right, * producing and concatenating observables along the way. * * It's the combination between [[scan0]] and [[flatMap]]. */ final def flatScan0[R](seed: => R)(op: (R, A) => Observable[R]): Observable[R] = Observable.eval(seed).flatMap(s => s +: flatScan(s)(op)) /** Version of [[flatScan]] that delays the errors from the emitted * streams until the source completes. * * \$delayErrorsDescription * * @see [[flatScan]] */ final def flatScanDelayErrors[R](seed: => R)(op: (R, A) => Observable[R]): Observable[R] = new FlatScanObservable[A, R](self, seed _, op, delayErrors = true) /** Version of [[flatScan0]] that delays the errors from the emitted * streams until the source completes. * * \$delayErrorsDescription * * @see [[flatScan0]] */ final def flatScan0DelayErrors[R](seed: => R)(op: (R, A) => Observable[R]): Observable[R] = Observable.eval(seed).flatMap(s => s +: flatScanDelayErrors(s)(op)) /** \$concatDescription * * Alias for [[Observable!.concat concat]]. * * @return \$concatReturn */ final def flatten[B](implicit ev: A <:< Observable[B]): Observable[B] = concat /** \$concatDescription * * ==Equivalence with concatMap== * * The `concat` operation is basically `concatMap` with the * identity function, as you can count on this equivalence: * * `stream.concat <-> stream.concatMap(x => x)` * * == Visual Example == * *
* streamA: a1 -- -- a2 -- -- a3 -- a4 -- --
* streamB: b1 -- -- b2 -- b3 -- -- -- -- b4
*
* result: a1, a2, a3, a4, b1, b2, b3, b4
*
* streamA: a1 -- -- a2 -- -- a3 -- a4 -- --
* streamB: b1 -- -- b2 -- b3 -- -- -- -- b4
*
* result: a1, b1, a2, b2, b3, a3, a4, b4
*
* * @note \$defaultOverflowStrategy * @return \$mergeReturn */ final def merge[B](implicit ev: A <:< Observable[B], os: OverflowStrategy[B] = OverflowStrategy.Default): Observable[B] = self.mergeMap(x => x)(os) /** Concurrently merges the observables emitted by the source with * the given generator function into a single observable. * * \$concatMergeDifference * * ==Example== * {{{ * Observable(1, 2, 3).mergeMap { x => * Observable.eval(println(s"Processing \$\$x")) * .executeAsync * .flatMap(_ => Observable(x, x)) * } * }}} * * In this example the source will yield 3 streams and those 3 * streams are being subscribed immediately, therefore the order of * the events will be non-deterministic, as the streams will be * evaluated concurrently. * * == Visual Example == * *
* streamA: a1 -- -- a2 -- -- a3 -- a4 -- --
* streamB: b1 -- -- b2 -- b3 -- -- -- -- b4
*
* result: a1, b1, a2, b2, b3, a3, a4, b4
*
* val B = implicitly[Monoid[B]]
*
* stream.scanMap(f) <-> stream.scan(B.empty)(B.combine)
*
* * Example: * {{{ * import cats.implicits._ * * // Yields 2, 6, 12, 20, 30, 42 * val stream = Observable(1, 2, 3, 4, 5, 6).scanMap(x => x * 2) * }}} * * @param f is the mapping function applied to every incoming element of this `Observable` * before folding using `Monoid[B].combine` * * @return a new `Observable` that emits all intermediate states being * resulted from applying `Monoid[B].combine` function */ final def scanMap[B](f: A => B)(implicit B: Monoid[B]): Observable[B] = self.scan(B.empty)((acc, a) => B.combine(acc, f(a))) /** Given a mapping function that returns a `B` type for which we have * a [[cats.Monoid]] instance, returns a new stream that folds the incoming * elements of the sources using the provided `Monoid[B].combine`, with the * initial seed being the `Monoid[B].empty` value, emitting the generated values * at each step. * * This is a version of [[scanMap]] that emits seed element at the beginning. */ final def scanMap0[B](f: A => B)(implicit B: Monoid[B]): Observable[B] = B.empty +: scanMap(f) /** Creates a new Observable that emits the given elements and then * it also emits the events of the source (prepend operation). */ final def startWith[B >: A](elems: Seq[B]): Observable[B] = Observable.fromIterable(elems) appendAll self /** Returns a new Observable that uses the specified `Scheduler` for * initiating the subscription. * * This is different from [[executeOn]] because the given `scheduler` * is only used to start the subscription, but does not override the * default [[monix.execution.Scheduler Scheduler]]. */ final def subscribeOn(scheduler: Scheduler): Observable[A] = new SubscribeOnObservable[A](self, scheduler) /** In case the source is empty, switch to the given backup. */ final def switchIfEmpty[B >: A](backup: Observable[B]): Observable[B] = new SwitchIfEmptyObservable[B](self, backup) /** Drops the first element of the source observable, * emitting the rest. */ final def tail: Observable[A] = drop(1) /** Drops the first `n` elements (from the start). * * @param n the number of elements to drop * @return a new Observable that drops the first ''n'' elements * emitted by the source */ final def drop(n: Int): Observable[A] = self.liftByOperator(new DropFirstOperator(n)) /** Creates a new Observable that emits the events of the source, only * for the specified `timestamp`, after which it completes. * * @param timespan the window of time during which the new Observable * is allowed to emit the events of the source */ final def takeByTimespan(timespan: FiniteDuration): Observable[A] = new TakeLeftByTimespanObservable(self, timespan) /** Creates a new Observable that emits every n-th event from the source, * dropping intermediary events. */ final def takeEveryNth(n: Int): Observable[A] = self.liftByOperator(new TakeEveryNthOperator(n)) /** Creates a new observable that mirrors the source until * the given `trigger` emits either an element or `onComplete`, * after which it is completed. * * The resulting observable is completed as soon as `trigger` * emits either an `onNext` or `onComplete`. If `trigger` * emits an `onError`, then the resulting observable is also * completed with error. * * @param trigger is an observable that will cancel the * streaming as soon as it emits an event */ final def takeUntil(trigger: Observable[Any]): Observable[A] = new TakeUntilObservable[A](self, trigger) /** Takes longest prefix of elements that satisfy the given predicate * and returns a new Observable that emits those elements. */ final def takeWhile(p: A => Boolean): Observable[A] = self.liftByOperator(new TakeByPredicateOperator(p)) /** Takes longest prefix of elements while given [[monix.execution.cancelables.BooleanCancelable BooleanCancelable]] * is not canceled and returns a new Observable that emits those elements. */ final def takeWhileNotCanceled(c: BooleanCancelable): Observable[A] = self.liftByOperator(new TakeWhileNotCanceledOperator(c)) /** Returns an Observable that emits only the first item emitted by * the source Observable during sequential time windows of a * specified duration. * * This differs from [[Observable!.throttleLast]] in that this only * tracks passage of time whereas `throttleLast` ticks at scheduled * intervals. * * @param interval time to wait before emitting another item after * emitting the last item */ final def throttleFirst(interval: FiniteDuration): Observable[A] = self.liftByOperator(new ThrottleFirstOperator[A](interval)) /** Emit the most recent items emitted by the source within * periodic time intervals. * * Alias for [[sample]]. * * @param period duration of windows within which the last item * emitted by the source Observable will be emitted */ final def throttleLast(period: FiniteDuration): Observable[A] = sample(period) /** Emit the most recent items emitted by the source within * periodic time intervals. * * Use the `sample` operator to periodically look at an observable * to see what item it has most recently emitted since the previous * sampling. Note that if the source observable has emitted no * items since the last time it was sampled, the observable that * results from the `sample` operator will emit no item for that * sampling period. * * @see [[sampleBy]] for fine control * @see [[sampleRepeated]] for repeating the last value on silence * @param period the timespan at which sampling occurs */ final def sample(period: FiniteDuration): Observable[A] = self.sampleBy(Observable.intervalAtFixedRate(period, period)) /** Returns an observable that, when the specified sampler * emits an item or completes, emits the most recently emitted item * (if any) emitted by the source since the previous * emission from the sampler. * * Use the `sampleBy` operator to periodically look at an observable * to see what item it has most recently emitted since the previous * sampling. Note that if the source observable has emitted no * items since the last time it was sampled, the observable that * results from the `sampleBy` operator will emit no item. * * @see [[sample]] for periodic sampling * @see [[sampleRepeatedBy]] for repeating the last value on silence * @param sampler - the observable to use for sampling the source */ final def sampleBy[B](sampler: Observable[B]): Observable[A] = new ThrottleLastObservable[A, B](self, sampler, shouldRepeatOnSilence = false) /** Only emit an item from an observable if a particular timespan has * passed without it emitting another item. * * Note: If the source observable keeps emitting items more * frequently than the length of the time window, then no items will * be emitted by the resulting observable. * * Alias for [[debounce]]. * * @param timeout the length of the window of time that must pass after * the emission of an item from the source observable in * which that observable emits no items in order for the * item to be emitted by the resulting observable * @see [[echoOnce]] for a similar operator that also mirrors * the source observable */ final def throttleWithTimeout(timeout: FiniteDuration): Observable[A] = debounce(timeout) /** Only emit an item from an observable if a particular timespan has * passed without it emitting another item. * * Note: If the source observable keeps emitting items more * frequently than the length of the time window, then no items will * be emitted by the resulting observable. * * @param timeout the length of the window of time that must pass after * the emission of an item from the source observable in * which that observable emits no items in order for the * item to be emitted by the resulting observable * @see [[echoOnce]] for a similar operator that also mirrors * the source observable */ final def debounce(timeout: FiniteDuration): Observable[A] = new DebounceObservable(self, timeout, repeat = false) /** Returns an observable that mirrors the source but that will trigger a * [[monix.execution.exceptions.DownstreamTimeoutException DownstreamTimeoutException]] * in case the downstream subscriber takes more than the given timespan * to process an `onNext` message. * * Note that this ignores the time it takes for the upstream to send * `onNext` messages. For detecting slow producers see [[timeoutOnSlowUpstream]]. * * @param timeout maximum duration for `onNext`. */ final def timeoutOnSlowDownstream(timeout: FiniteDuration): Observable[A] = new DownstreamTimeoutObservable[A](self, timeout) /** Returns an observable that mirrors the source but applies a timeout * for each emitted item by the upstream. If the next item isn't * emitted within the specified timeout duration starting from its * predecessor, the source is terminated and the downstream gets * subscribed to the given backup. * * Note that this ignores the time it takes to process `onNext`. * If dealing with a slow consumer, see [[timeoutOnSlowDownstream]]. * * @param timeout maximum duration between emitted items before * a timeout occurs (ignoring the time it takes to process `onNext`) * @param backup is the alternative data source to subscribe to on timeout */ final def timeoutOnSlowUpstreamTo[B >: A](timeout: FiniteDuration, backup: Observable[B]): Observable[B] = self.timeoutOnSlowUpstream(timeout).onErrorHandleWith { case UpstreamTimeoutException(`timeout`) => backup case other => Observable.raiseError(other) } /** Returns an observable that mirrors the source but applies a timeout * for each emitted item by the upstream. If the next item isn't * emitted within the specified timeout duration starting from its * predecessor, the resulting Observable terminates and notifies * observers of a TimeoutException. * * Note that this ignores the time it takes to process `onNext`. * If dealing with a slow consumer, see [[timeoutOnSlowDownstream]]. * * @param timeout maximum duration between emitted items before * a timeout occurs (ignoring the time it takes to process `onNext`) */ final def timeoutOnSlowUpstream(timeout: FiniteDuration): Observable[A] = new UpstreamTimeoutObservable[A](self, timeout) /** While the destination observer is busy, buffers events, applying * the given overflowStrategy. * * @param overflowStrategy - \$overflowStrategyParam */ final def whileBusyBuffer[B >: A](overflowStrategy: OverflowStrategy.Synchronous[B]): Observable[B] = asyncBoundary(overflowStrategy) /** \$asyncBoundaryDescription * * @param overflowStrategy - \$overflowStrategyParam */ final def asyncBoundary[B >: A](overflowStrategy: OverflowStrategy[B]): Observable[B] = liftByOperator(new AsyncBoundaryOperator[B](overflowStrategy)) /** While the destination observer is busy, drop the incoming events. */ final def whileBusyDropEvents: Observable[A] = self.liftByOperator(new WhileBusyDropEventsOperator[A]) /** While the destination observer is busy, drop the incoming events. * When the downstream recovers, we can signal a special event * meant to inform the downstream observer how many events where * dropped. * * @param onOverflow - \$onOverflowParam */ final def whileBusyDropEventsAndSignal[B >: A](onOverflow: Long => B): Observable[B] = self.liftByOperator(new WhileBusyDropEventsAndSignalOperator[B](onOverflow)) /** Combines the elements emitted by the source with the latest element * emitted by another observable. * * Similar with `combineLatest`, but only emits items when the single source * emits an item (not when any of the Observables that are passed to the operator * do, as combineLatest does). * * == Visual Example == * *
* stream1: 1 - - 2 - - 3 - 4 - -
* stream2: 1 - - 2 - 3 - - - - 4
*
* result: (1, 1), (2, 2), (3, 3), (4, 3)
*
* * @param other is an observable that gets paired with the source * @param f is a mapping function over the generated pairs */ final def withLatestFrom[B, R](other: Observable[B])(f: (A, B) => R): Observable[R] = new WithLatestFromObservable[A, B, R](self, other, f) /** Combines the elements emitted by the source with the latest elements * emitted by two observables. * * Similar with `combineLatest`, but only emits items when the single source * emits an item (not when any of the Observables that are passed to the operator * do, as combineLatest does). * * @param o1 is the first observable that gets paired with the source * @param o2 is the second observable that gets paired with the source * @param f is a mapping function over the generated pairs */ final def withLatestFrom2[B1, B2, R](o1: Observable[B1], o2: Observable[B2])(f: (A, B1, B2) => R): Observable[R] = self.withLatestFrom(Observable.combineLatest2(o1, o2)) { (a, tuple) => f(a, tuple._1, tuple._2) } /** Combines the elements emitted by the source with the latest elements * emitted by three observables. * * Similar with `combineLatest`, but only emits items when the single source * emits an item (not when any of the Observables that are passed to the operator * do, as combineLatest does). * * @param o1 is the first observable that gets paired with the source * @param o2 is the second observable that gets paired with the source * @param o3 is the third observable that gets paired with the source * @param f is a mapping function over the generated pairs */ final def withLatestFrom3[B1, B2, B3, R](o1: Observable[B1], o2: Observable[B2], o3: Observable[B3]) (f: (A, B1, B2, B3) => R): Observable[R] = { self.withLatestFrom(Observable.combineLatest3(o1, o2, o3)) { (a, o) => f(a, o._1, o._2, o._3) } } /** Combines the elements emitted by the source with the latest elements * emitted by four observables. * * Similar with `combineLatest`, but only emits items when the single source * emits an item (not when any of the Observables that are passed to the operator * do, as combineLatest does). * * @param o1 is the first observable that gets paired with the source * @param o2 is the second observable that gets paired with the source * @param o3 is the third observable that gets paired with the source * @param o4 is the fourth observable that gets paired with the source * @param f is a mapping function over the generated pairs */ final def withLatestFrom4[B1, B2, B3, B4, R]( o1: Observable[B1], o2: Observable[B2], o3: Observable[B3], o4: Observable[B4]) (f: (A, B1, B2, B3, B4) => R): Observable[R] = { self.withLatestFrom(Observable.combineLatest4(o1, o2, o3, o4)) { (a, o) => f(a, o._1, o._2, o._3, o._4) } } /** Combines the elements emitted by the source with the latest elements * emitted by five observables. * * Similar with `combineLatest`, but only emits items when the single source * emits an item (not when any of the Observables that are passed to the operator * do, as combineLatest does). * * @param o1 is the first observable that gets paired with the source * @param o2 is the second observable that gets paired with the source * @param o3 is the third observable that gets paired with the source * @param o4 is the fourth observable that gets paired with the source * @param o5 is the fifth observable that gets paired with the source * @param f is a mapping function over the generated pairs */ final def withLatestFrom5[B1, B2, B3, B4, B5, R]( o1: Observable[B1], o2: Observable[B2], o3: Observable[B3], o4: Observable[B4], o5: Observable[B5]) (f: (A, B1, B2, B3, B4, B5) => R): Observable[R] = { self.withLatestFrom(Observable.combineLatest5(o1, o2, o3, o4, o5)) { (a, o) => f(a, o._1, o._2, o._3, o._4, o._5) } } /** Combines the elements emitted by the source with the latest elements * emitted by six observables. * * Similar with `combineLatest`, but only emits items when the single source * emits an item (not when any of the Observables that are passed to the operator * do, as combineLatest does). * * @param o1 is the first observable that gets paired with the source * @param o2 is the second observable that gets paired with the source * @param o3 is the third observable that gets paired with the source * @param o4 is the fourth observable that gets paired with the source * @param o5 is the fifth observable that gets paired with the source * @param o6 is the sixth observable that gets paired with the source * @param f is a mapping function over the generated pairs */ final def withLatestFrom6[B1, B2, B3, B4, B5, B6, R]( o1: Observable[B1], o2: Observable[B2], o3: Observable[B3], o4: Observable[B4], o5: Observable[B5], o6: Observable[B6]) (f: (A, B1, B2, B3, B4, B5, B6) => R): Observable[R] = { self.withLatestFrom(Observable.combineLatest6(o1, o2, o3, o4, o5, o6)) { (a, o) => f(a, o._1, o._2, o._3, o._4, o._5, o._6) } } /** Creates a new observable from this observable and another given * observable by combining their items in pairs in a strict sequence. * * So the first item emitted by the new observable will be the tuple of the * first items emitted by each of the source observables; the second item * emitted by the new observable will be a tuple with the second items * emitted by each of those observables; and so forth. * * == Visual Example == * *
* stream1: 1 - - 2 - - 3 - 4 - -
* stream2: 1 - - 2 - 3 - - - - 4
*
* result: (1, 1), (2, 2), (3, 3), (4, 4)
*
* * See [[combineLatest]] for a more relaxed alternative that doesn't * combine items in strict sequence. * * @param other is an observable that gets paired with the source * @return a new observable sequence that emits the paired items * of the source observables */ final def zip[B](other: Observable[B]): Observable[(A, B)] = new Zip2Observable[A, B, (A, B)](self, other)((a, b) => (a, b)) /** Creates a new observable from this observable and another given * observable by combining their items in pairs in a strict sequence. * * So the first item emitted by the new observable will be the result * of the function applied to the first item emitted by each of * the source observables; the second item emitted by the new observable * will be the result of the function applied to the second item * emitted by each of those observables; and so forth. * * == Visual Example == * *
* stream1: 1 - - 2 - - 3 - 4 - -
* stream2: 1 - - 2 - 3 - - - - 4
*
* result: (1, 1), (2, 2), (3, 3), (4, 4)
*