0

So this is basically how my code looks. I run a request, when it's finished and i get some result, i run the next. I do this 3 times, however, it just dies efter the first one and wont continue.

private func getSomething(with model: SomeModel) {
        networker.runRequest(.getSomething, model: Something.self)
            .receiveOnMain()
            .sink { [weak self] completion in
                self?.handleCompletion(completion: completion)
            } receiveValue: { [weak self] model in
                self?.getData(with: model)
                
            }
            .store(in: &cancellableSet)
    }
    
    func getData(with model: SomeModel) {
        networker.runRequest(.getData, model: DataModel.self)
            .recieveOnMain()
            .sink { [weak self] completion in
                self?.handleCompletion(completion: completion)
            } receiveValue: { secondaryModel in
                print("complete")
            }
            .store(in: &cancellableSet)
    }

    func getSomethingElse(with somethingElse: SomeModel) {
        networker.runRequest(.getSomethingElse, model: SomethingElse.self)
            .recieveOnMain()
            .sink { [weak self] completion in
                self?.handleCompletion(completion: completion)
            } receiveValue: { secondaryModel in
                print("complete")
            }
            .store(in: &cancellableSet)
    }

the networker looks like this:

func executeRequest<T: Decodable>(requestModel: NewRequestable, triesLeft: Int, model: T.Type) -> AnyPublisher<T, Error> {
    urlSession.createDataTaskPublisher(for: requestModel.buildRequest())
        .mapError { $0 as Error }
        .flatMap({
            self.publisher(forDataTaskOutput: $0, requestModel: requestModel, triesLeft: triesLeft, model: model)
        })
        .eraseToAnyPublisher()
}

where the self.publisher func looks like:

private func publisher<T: Decodable>(forDataTaskOutput output: URLSession.DataTaskPublisher.Output, requestModel: NewRequestable, triesLeft: Int, model: T.Type) -> AnyPublisher<T, Error> {
    switch (output.response as? HTTPURLResponse)?.statusCode {
    case .some(200...399):
        return Just(output.data)
            .decode(type: T.self, decoder: JSONDecoder())
            .mapError { error -> APIError in
                APIError.apiError(reason: error.localizedDescription)
            }
            .eraseToAnyPublisher()
    case .some(401) where triesLeft > 0:
        return authenticator.updateToken()
            .flatMap { tokenResponse -> AnyPublisher<T, Error> in
                self.authenticator.token = .OAuth2(tokenResponse.access_token)
                return self.executeRequest(requestModel: requestModel, triesLeft: triesLeft - 1, model: model) }
            .eraseToAnyPublisher()
    default:
        return Result.failure(NSError(domain: "", code: 1, userInfo: nil)).publisher.eraseToAnyPublisher()
    }
}

It however the second request never gets to the publisher func. Why is this? Is it queing up something somehow?

Edit: According to charles proxy, the second request is never executed at all.

Edit 2: I noticed it works if i remove the .recieveOnMain() from each publisher. But then it complains that i have to run the recieveValue in the sink on main thread. so kinda stuck

Vollan
  • 1,887
  • 11
  • 26

1 Answers1

1

Assuming receiveOnMain has the implementation of receive(on: DispatchQueue.global()), when you call getSomething(with:) then the only way that getData(with:) won't get called is if:

  • self went out of scope.
  • runRequest(.getSomething, model: Something.self) did not emit a next event.
  • cancellableSet was deinited.

Track down which of the three above apply and fix the problem associated with it.

Daniel T.
  • 32,821
  • 6
  • 50
  • 72
  • Thank you for your answer. It seems like the problem was inside recieveOnMain() as it does .recieve(on: RunLoop.main). And that probably made the next networkRequest to be on mainThread. Which resulted in no request at all somehow – Vollan Oct 05 '21 at 16:51
  • That won't do it. Notice that your first `runRequest` is called on main and has no problem with running. I see that you or your team wrote a `createDataTaskPublisher` method rather than just using the `dataTaskPublisher` method that Apple provides... Maybe it's doing something wrong. – Daniel T. Oct 05 '21 at 17:57