0

I'm very new to the concept Publishers and I'm creating a networking service using dataTaskPublisher on URLSession. There is a case for refreshing token and I have a refreshToken() method which returns AnyPublisher<Bool, Never>:

    func refreshToken() -> AnyPublisher<Bool, Never> {
        var disposable = Set<AnyCancellable>()
        
        do {
            let request = URLRequest(url: URL(string: "refresh_token_url")!)
            URLSession.shared.dataTaskPublisher(for: request).sink { finished in
                /// Compiler error: Cannot convert value of type 'AnyPublisher<Bool, Never>' to closure result type 'Void'
                return Just(false).eraseToAnyPublisher()
            } receiveValue: { _ in
                /// What should I return here?
                return Just(true).eraseToAnyPublisher()
            }.store(in: &disposable)

        } catch {
            return Just(false).eraseToAnyPublisher()
        }
        
    }

Compiler complains for both of Just().eraseToAnyPublisher(). I don't know how and where should return Just(false).eraseToAnyPublisher() based on success or failure of this refresh token call.

Maysam
  • 7,246
  • 13
  • 68
  • 106
  • What are you trying to do? You cannot both return an AnyPublisher and attach a sink-and-store to your publisher. If the goal is simply to set up the publisher, delete the sink-and-store part and just return the data task publisher (type-erased). Also it is utterly pointless to `store` in a local, as it does not persist (but my guess is that you have no need to be storing at all). – matt Mar 21 '22 at 19:26
  • I know it's frustrating but may I suggest you stop dead in your tracks and learn about Combine before you try to use it. By an amazing coincidence I've written a free online book that teaches it to you: https://www.apeth.com/UnderstandingCombine/ – matt Mar 21 '22 at 19:28
  • @matt here i'm trying to catch 401 error and refresh the token then re-try the call, this `refreshToken` is called inside `tryCatch` of another `dataTaskPublisher`, and sure, i'll read about it more (I did read a bit already). – Maysam Mar 21 '22 at 20:39
  • Until you have a better mental image of what a Combine pipeline is and how to use it, let's put the matter on hold. – matt Mar 21 '22 at 21:19
  • well, Unfortunately I don't have much to refactor it. I removed sink and used `replaceError` operator. I guess it's going to work. – Maysam Mar 21 '22 at 21:28

1 Answers1

1

It is the caller of this function who will need to store the token (AnyCancellable) so there is no need for the sink (which is the reason for the error you are seeing). There is no need to wrap a publisher in a do-try-catch block.

This approach would compile:

func refreshToken() -> AnyPublisher<Bool, Never> {
    let request = URLRequest(url: URL(string: "refresh_token_url")!)
    return URLSession.shared
        .dataTaskPublisher(for: request)
        .map { _ in true }
        .replaceError(with: false)
        .eraseToAnyPublisher()
}

Though it does not make much sense for a method called refreshToken to return a Bool. You should decode the response, extract the token and publish that (AnyPublisher<String, Error>).

LuLuGaGa
  • 13,089
  • 6
  • 49
  • 57