订阅

订阅

GraphQL支持订阅,允许客户端在服务器上的数据发生更改时立即进行更新。

Apollo iOS库主要通过ApolloWebSocket支持订阅的使用,这是一个可选的附加库,它使用流行的iOS WebSocket库Starscream来连接到GraphQL服务器。

通过代码生成还支持订阅:每当声明订阅字段时,都会生成符合GraphQLSubscription的操作,该操作允许传递订阅字段所接受的任何参数。

生成这些操作之后,可以使用支持订阅的网络传输使用ApolloClient实例进行订阅,并继续接收有关更改的更新,直到取消订阅。

支持订阅的传输类型

有两个不同的类符合ApolloWebSocket库中的网络传输协议:

WebSocketTransport通过一个web套接字发送所有操作。 SplitNetworkTransport挂载于WebSocketTransport实例和UploadingNetworkTransport实例(通常是HTTPNetworkTransport),以便创建单个网络传输,该传输可以使用http进行查询和转换,使用web sockets进行订阅。 通常,使用SplitNetworkTransport,因为这允许保留单个网络传输设置,并避免使用多个客户端对象的任何潜在问题。

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  } }

在标准的HTTP操作中,如果需要身份验证,通常会发送一个授权头和请求。但是,对于web套接字,由于需要持久连接,因此不能将其与每个有效负载一起发送。

对于web套接字,connectingPayload提供了那些通常作为请求头的一部分指定的参数。

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) } 

猜你喜欢

转载自www.cnblogs.com/liuxiaokun/p/12676847.html