用Promises链接网络呼叫

时间:2017-11-02 21:05:11

标签: ios swift promise

我在https://github.com/khanlou/Promise

使用了承诺库

如果我想连接多个网络电话,我该怎么做呢?每个调用都有一组不同的参数,并返回一个Promise< [String:Any]>

理想情况下,我只会存储每个.then闭包的结果,然后只返回下一个调用:

  typealias GetPromise = Promise<[String:Any]>

  getDomains(baseDomain: credentials.baseDomain).then({ domains in
     self.domains = domains
     return self.getConfiguration(baseDomain: credentials.baseDomain, brandId: credentials.brandId)
  }).then({ configuration in
     self.configuration = configuration
     return self.getServerTime(baseDomain: credentials.baseDomain)
  }).then({ serverTime in
     self.serverTime = serverTime
     resultsBlock(Results.success)
  }).catch { (error) in
     resultsBlock(Results.error(error))
  }

不幸的是,它违反了语音功能规则中的非空返回值。

然后我尝试将每个调用的结果与下一个作为元组的承诺一起返回,但这导致了解构问题:

  typealias GetPromise = Promise<[String:Any]>

  getDomains(baseDomain: credentials.baseDomain).then({ domains in
     return (domains, self.getConfiguration(baseDomain: credentials.baseDomain, brandId: credentials.brandId))
  }).then({ (domains, configuration) in
     return (domains, configuration, self.getServerTime(baseDomain: credentials.baseDomain))
  }).then({ (domains, configuration, serverTime) in
     resultsBlock(Results.succes)
  }).catch { (error) in
     resultsBlock(Results.error(error))
  }

以下是我的方法定义:

   private func getDomains(baseDomain: String) -> GetPromise {
      return get(urlPath: discoveryPath)
   }

   private func getConfiguration(baseDomain: String, brandId: String) -> GetPromise {
      return get(urlPath: configurationPath)
   }

   private func getServerTime(baseDomain: String) -> GetPromise {
      return get(urlPath: serverTimePath)
   }

   private func get(urlPath: String) -> GetPromise {
      return GetPromise(work: { fulfill, reject in
         guard let url = URL(string: urlPath) else {
            reject(ConnectionManager.basicError)
            return
         }

         let task = URLSession.shared.dataTask(with: url) {(data, _, error) in
            if let error = error {
               reject(error)
               return
            }

            if let data = data
               , let jsonObject = try? JSONSerialization.jsonObject(with: data, options: [])
               , let dictValue = jsonObject as? [String:Any] {
               fulfill(dictValue)
               return
            }

            reject(ConnectionManager.basicError)
         }

         task.resume()
      })
   }

有什么想法吗?也许Promises不是这里的方式,有一种方式以类似的方式包装网络呼叫?

1 个答案:

答案 0 :(得分:0)

来自产品所有者:

你的第一段代码工作正常,你只需要一个返回类型的块。例如,配置 - &gt;承诺&lt; [String:Any]&gt;这是因为长于一行的块不会在Swift中推断出它们的类型。

如果所有请求完全独立,您可以使用Promises.zip。

Promises.zip(
    getDomains(baseDomain: credentials.baseDomain),
    self.getConfiguration(baseDomain: credentials.baseDomain, brandId: credentials.brandId),
    self.getServerTime(baseDomain: credentials.baseDomain)
).then({ (domains, configuration, time) in
   // save all data

希望有所帮助。