Combine - My Custom Publisher Is Not Publish

Viewed 26

I've been working on GraphQL for a while and I wanted to use custom publisher and Apollo together. But some kind of custom publisher didn't work, I've been dealing with it for days. I couldn't find what I missed

note: After running fetchPublisher(), no error or data is returned.

Custom Publisher

import Foundation
import Apollo
import Combine

struct ApolloPublisher<Query: GraphQLQuery>: Publisher {
    
    typealias Output = GraphQLResult<Query.Data>
    typealias Failure = Error
    
    private let client: ApolloClient
    private let query: Query
    
    init(client:ApolloClient,
         query: Query) {
        self.client = client
        self.query = query
    }
    
    func receive<S>(subscriber: S) where S : Subscriber, S.Failure == Error, S.Input == GraphQLResult<Query.Data> {
        let subscription = ApolloSubscription(client: self.client,
                                                    query: self.query,
                                                    subscriber: subscriber)
        subscriber.receive(subscription: subscription)
    }
}

Custom Subscription

import Foundation
import Apollo
import Combine

final class ApolloSubscription<GraphQuery: GraphQLQuery, SubscriberType: Subscriber>: Subscription where SubscriberType.Input == GraphQLResult<GraphQuery.Data>, SubscriberType.Failure == Error {

private let subscriber: SubscriberType
private var cancelable: Apollo.Cancellable?

init(client: ApolloClient,
     query: GraphQuery,
     subscriber: SubscriberType) {
    self.subscriber = subscriber
    self.cancelable = client.fetch(query: query,
                                   resultHandler: self.handle)
}

deinit {
    cancelable?.cancel()
}

func request(_ demand: Subscribers.Demand) {}

func cancel() {
    cancelable?.cancel()
    cancelable = nil
}

func handle(result: Result<GraphQLResult<GraphQuery.Data>, Error>) {
    switch result {
    case .success(let resultSet):
        _ = subscriber.receive(resultSet)
    case .failure(let error):
        subscriber.receive(completion: .failure(error))
    }
    subscriber.receive(completion: .finished)
    }
}

extension for ApolloClient

extension ApolloClient {
    func fetchPublisher<Query: GraphQLQuery>(query: Query) -> ApolloPublisher<Query> {
        return ApolloPublisher(client: self,
                               query: query)
    }
}

Client side.

let apollo = ApolloClient(url: URL(string: "https://api.spacex.land/graphql/")!)

func fetch() -> AnyPublisher<String, Error> {
    return apollo.fetchPublisher(query: GetLaunchesQuery())
        .mapError { error in
            return error
        }
        .map { response in
           return response.data?.launches?.description ?? ""
        }
        .eraseToAnyPublisher()
}
0 Answers
Related