'How to merge two publishers with Combine?

I have an token publisher. It returns a token value as string. I want to make a request using this token in request publisher. I have no idea how to do it. Maybe these codes will help.

Token Transactions:

// Token Publisher
func getAccessToken() -> AnyPublisher<String, Error> {
    let url = "it doesn't matter"
    var urlRequest = URLRequest(url: url)
    // some url request setups
    // ...
    return URLSession.shared
        .dataTaskPublisher(for: urlRequest)
        .map(\.data)
        .decode(type: AccessToken.self, decoder: JSONDecoder())
        .map({ $0.token ?? "" })
        .receive(on: DispatchQueue.main)
        .eraseToAnyPublisher()
}

Generic Request Transactions:

// Request Publisher (The T is decodable generic type.)
func request<T: Decodable>(ofType: T.Type, apiURL: APIURL, method: HTTPMethods) -> AnyPublisher<T, Error> {
    // This flatMap is not invoked. :/
    AuthManager.shared.getAccessToken()
        .flatMap({ accessToken -> AnyPublisher<T, Error> in
            guard let url = URL(string: apiURL.url) else {
                return Fail(error: NSError(domain: "Missing API URL", code: -10001, userInfo: nil)).eraseToAnyPublisher()
            }
            var urlRequest = URLRequest(url: url)
            urlRequest.httpMethod = method.rawValue
            urlRequest.setValue("Authorization", forHTTPHeaderField: "Bearer " + accessToken)
            return URLSession.shared
                .dataTaskPublisher(for: urlRequest)
                .map(\.data)
                .decode(type: T.self, decoder: JSONDecoder())
                .eraseToAnyPublisher()
        }).eraseToAnyPublisher()
}

Example Request Transactions:

// Example Request
private var cancellables = Set<AnyCancellable>()

func getExampleRequest(id: String) {
    let url = "it doesn't matter"
    APIManager.shared.request(ofType: ExampleModel.self, apiURL: url, method: .get).sink { completion in
        switch completion {
        case .finished:
            break
        case .failure(let error):
            print(error)
        }
    } receiveValue: { exampleModelData in
        // print(exampleModelData)
    }.store(in: &cancellables)
}

Thanks in advance.



Solution 1:[1]

What you have here is a runtime problem that isn't reproducible given the code you presented. I can't give you an answer but I can help you find the problem.

The .print() operator is your friend. put it just before the flatMap and you should see that you aren't getting a next event, but you will likely see that you are getting a canceled or finished event.

If you are getting a finished event, move the print operator up the publisher chain until you figure out where the problem is. If you are getting a cancelled event, check to see why your cancellable is being deinted before completion.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1