Michael Ozeryansky
Michael Ozeryansky

Reputation: 8053

Is there a reactive function which executes and passes the original value?

I have a flow which transforms data, acts on it, transform it again, and acts on that. For example:

// Current code
Just(0)
    .map({ $0 + 1 })
    .map({ funcX($0); return $0 })
    .map({ $0 + 1 })
    .map({ funcY($0); return $0 })
    ...

I know reactive programming is about streams, but I would like to call funcX without needing to return the value. Is there a function which passes in the value and automatically passes along the value? Something like:

// Hypothetical
Just(0)
    .map({ $0 + 1 })
    .call({ funcX($0) })
    .map({ $0 + 1 })
    .call({ funcY($0) })
    ...

Note: The above swift needs more syntax to actually compile, just is an example.

Upvotes: 3

Views: 88

Answers (2)

Gil Birman
Gil Birman

Reputation: 35900

No need for a custom operator, one already exists: handleEvents

Just(0)
    .map({ $0 + 1 })
    .handleEvents(receiveOutput: { funcX($0) })
    .map({ $0 + 1 })
    .handleEvents(receiveOutput: { funcY($0) })
    ...

The handleEvents operator can hook into any part of the publisher/subscriber lifecycle with it's optional parameters:

  • receiveSubscription

  • receiveRequest

  • receiveCancel

  • receiveOutput

  • receiveCompletion

Upvotes: 2

Asperi
Asperi

Reputation: 257711

Of course you can write your own operator, but as for me there is simpler approach, based on default operators, having handler, eg:

extension Publisher {

/// Republishes all elements that match a provided closure.
///
/// - Parameter isIncluded: A closure that takes one element and returns a Boolean value indicating whether to republish the element.
/// - Returns: A publisher that republishes all elements that satisfy the closure.
public func filter(_ isIncluded: @escaping (Self.Output) -> Bool) -> Publishers.Filter<Self>

so your case would look like

.filter({ funcX($0); return true })

as a result you have transparent stream and possibility to execute any callback on Downstream values.

You can even wrap it, like

extension Publisher {
    public func call(_ closure: @escaping (Self.Output) -> Void) -> Publishers.Filter<Self> {
        return self.filter({ closure($0); return true })
    }
}

Upvotes: 2

Related Questions