• 订阅


    订阅

    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)
    }
    
  • 相关阅读:
    Beta阶段代码规范与计划
    Alpha总结展望——前事不忘后事之师
    Alpha冲刺成果测试
    Alpha冲刺总结
    码到成功——Beta冲刺随笔 day 5
    码到成功——Beta冲刺随笔 day 4
    码到成功——Beta冲刺随笔 day 3
    码到成功——Beta冲刺随笔 day 2
    码到成功——Beta冲刺随笔 day 1
    项目Beta冲刺(团队)——凡事预则立
  • 原文地址:https://www.cnblogs.com/liuxiaokun/p/12676847.html
Copyright © 2020-2023  润新知