subscription

subscription

GraphQL supports subscriptions, allowing clients to update immediately when data on the server changes.

The Apollo iOS library mainly supports the use of subscriptions through ApolloWebSocket, which is an optional additional library that uses the popular iOS WebSocket library Starscream to connect to the GraphQL server.

Subscription is also supported through code generation: whenever a subscription field is declared, an operation that conforms to GraphQLSubscription is generated, which allows any parameters accepted by the subscription field to be passed.

After generating these operations, you can use the subscription-supported network transmission to subscribe using the ApolloClient instance and continue to receive updates about changes until the subscription is cancelled.

Supports subscribed transfer types

There are two different classes that conform to the network transmission protocol in the ApolloWebSocket library:

WebSocketTransport sends all operations through a web socket. SplitNetworkTransport is mounted on the WebSocketTransport instance and UploadingNetworkTransport instance (usually HTTPNetworkTransport) to create a single network transmission, which can be queried and converted using http and subscribed using web sockets. Generally, SplitNetworkTransport is used because this allows the retention of a single network transmission setting and avoids any potential problems with using multiple client objects.

import Foundation
import Apollo
import ApolloWebSocket

// MARK: - Singleton Wrapper  class Apollo {  static let shared = Apollo()   /// A web socket transport to use for subscriptions  private lazy var webSocketTransport: WebSocketTransport = {  let url = URL(string: "ws://localhost:8080/websocket")!  let request = URLRequest(url: url)  return WebSocketTransport(request: request)  }()   /// An HTTP transport to use for queries and mutations  private lazy var httpTransport: HTTPNetworkTransport = {  let url = URL(string: "http://localhost:8080/graphql")!  return HTTPNetworkTransport(url: url)  }()   /// A split network transport to allow the use of both of the above  /// transports through a single `NetworkTransport` instance.  private lazy var splitNetworkTransport = SplitNetworkTransport(  httpNetworkTransport: self.httpTransport,  webSocketNetworkTransport: self.webSocketTransport  )   /// Create a client using the `SplitNetworkTransport`.  private(set) lazy var client = ApolloClient(networkTransport: self.splitNetworkTransport) }

class ReviewViewController: UIViewController {

  private var subscription: Cancellable?
 private var reviewList = [Review]()   // Assume data source and delegate are hooked up in Interface Builder  @IBOutlet private var reviewTableView: UITableView!   override func viewDidLoad() {  super.viewDidLoad()   // Set the subscription variable up - be careful not to create a retain cycle!  self.subscription = Apollo.shared.client  .subscribe(subscription: ReviewAddedSubscription()) { [weak self] result in  guard let self = self else {  return  }   switch result {  case .success(let graphQLResult):  if let review = graphQLResult.data?.reviewAdded {  // A review was added - append it to the list then reload the data.  self.reviewList.append(review)  self.reviewTableView.reloadData()  } // else, something went wrong and you should check `graphQLResult.error` for problems  case .failure(let error):  // Not included here: Show some kind of alert  }  }  }   deinit {  // Make sure the subscription is cancelled, if it exists, when this object is deallocated.  self.subscription?.cancel()  }   // MARK: - Standard TableView Stuff   func tableView(_ tableView: UITableView,  numberOfRowsInSection section: Int) -> Int {  return self.reviewList.count  }   func tableView(_ tableView: UITableView,  cellForRowAt indexPath: IndexPath) -> UITableViewCell {  // Assume `ReviewCell` is a cell for displaying reviews created elsewhere  guard let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as? ReviewCell else {  return UITableViewCell()  }   let review = self.reviewList[indexPath.row]   cell.episode = review.episode  cell.stars = review.stars  cell.commentary = review.commentary   return cell  } }

In standard HTTP operations, if authentication is required, an authorization header and request are usually sent. However, for web sockets, since a persistent connection is required, it cannot be sent with every payload.

For web sockets, connectingPayload provides those parameters that are usually specified as part of the request header.

import Foundation
import Apollo
import ApolloWebSocket

// MARK: - Singleton Wrapper  let magicToken = "So long and thanks for all the fish"  class Apollo {  static let shared = Apollo()   /// A web socket transport to use for subscriptions  // This web socket will have to provide the connecting payload which  // initializes the connection as an authorized channel.  private lazy var webSocketTransport: WebSocketTransport = {  let url = URL(string: "ws://localhost:8080/websocket")!  let request = URLRequest(url: url)  let authPayload = ["authToken": magicToken]  return WebSocketTransport(request: request, connectingPayload: authPayload)  }()   /// An HTTP transport to use for queries and mutations.  private lazy var httpTransport: HTTPNetworkTransport = {  let url = URL(string: "http://localhost:8080/graphql")!  return HTTPNetworkTransport(url: url)  }()   /// A split network transport to allow the use of both of the above  /// transports through a single `NetworkTransport` instance.  private lazy var splitNetworkTransport = SplitNetworkTransport(  httpNetworkTransport: self.httpTransport,  webSocketNetworkTransport: self.webSocketTransport  )   /// Create a client using the `SplitNetworkTransport`.  private(set) lazy var client = ApolloClient(networkTransport: self.splitNetworkTransport) } 

Guess you like

Origin www.cnblogs.com/liuxiaokun/p/12676847.html