从 PromiseKit/Alamofire 返回一个 Promise
Posted
技术标签:
【中文标题】从 PromiseKit/Alamofire 返回一个 Promise【英文标题】:Returning a Promise from PromiseKit/Alamofire 【发布时间】:2016-11-16 17:34:53 【问题描述】:我正在尝试做这件看似微不足道的事情:
static func list() -> Promise<[Activity]>
let endpoint = "\(self.baseUrl)/v1/activities"
return Promise fulfill, reject in
self.fetchHeaders (headers) in
return Alamofire.request(
endpoint,
method: .get,
parameters: nil,
encoding: JSONEncoding.default,
headers: headers
).validate().responseJSON().then() response in
guard let json = response as? JSON else
reject(ActivityError.parse("Malformed JSON"))
guard let jsonActivities = json["activities"] as? [JSON] else
reject(ActivityError.parse("Missing field"))
var activities: [Activity] = []
for jsonActivity in jsonActivities
guard let activity = Activity(json: jsonActivity) else
reject(ActivityError.parse("Unable to parse an Activity object"))
activities.append(activity)
fulfill(activities)
.catch error in
reject(ActivityError.network("HTTP response failure"))
但是,编译器(理所当然地)抱怨:
'guard' body 可能不会掉下来,考虑使用 'return' 或 'break' 退出范围
我知道我需要在此处返回一个 Promise。我只是不知道在 reject() 和 fulfill() 调用下面到底要放什么。
【问题讨论】:
【参考方案1】:reject
或 fulfill
调用没有任何问题。问题是,在您的 guard
语句中 reject
之后,您还必须 return
退出关闭:
guard let json = response as? JSON else
reject(ActivityError.parse("Malformed JSON"))
return
guard let jsonActivities = json["activities"] as? [JSON] else
reject(ActivityError.parse("Missing field"))
return
关键是你不想将这个方法返回的承诺(后来被fulfill
或reject
满足)与在这个闭包中你必须立即退出的事实混为一谈在guard
子句中带有return
的闭包。
我无法用您的代码重现此问题(因为您没有提供MCVE 并且这里有一些我无法解决的参考资料)。但这里是您的代码的简化版本,说明了guard
的使用:
所以,如果不使用 PromiseKit/Alamofire,你可以这样做:
func list() -> Promise<[String: Any]>
return Promise fulfill, reject in
Alamofire.request(url)
.validate()
.responseJSON response in
switch response.result
case .success(let json):
guard let dictionary = json as? [String: Any] else
reject(ActivityError.malformed("not a dictionary"))
return
fulfill(dictionary)
case .failure(let error):
reject(error)
如您所见,您返回的是 Promise
,但在 Alamofire 闭包中,您只是退出了 guard
语句。
如果您使用 PromiseKit/Alamofire 并调用 then
,您可能想要创建一个可以返回的 Promise,例如:
func list() -> Promise<String>
return Alamofire.request(endPoint)
.validate()
.responseJSON()
.then value in
return Promise fulfill, reject in
guard let dictionary = value as? [String: Any], let name = dictionary["name"] as? String else
reject(ActivityError.malformed("not dictionary"))
return
fulfill(name)
或者如果这太麻烦了,你可以把value
的解析拉出来:
func list() -> Promise<String>
return Alamofire.request(endPoint)
.validate()
.responseJSON()
.then value in
self.parse(value)
func parse(_ value: Any) -> Promise<String>
return Promise fulfill, reject in
guard let dictionary = value as? [String: Any], let name = dictionary["name"] as? String else
reject(ActivityError.malformed("not dictionary"))
return
fulfill(name)
但是,无论哪种方式,即使使用 PromiseKit/Alamofire,您仍然只是在 guard
子句中使用 return
。
【讨论】:
那不行,我实际上需要在那里返回一个 Promise。返回 void 不会建立。 我试过了。请注意,我正在使用 PromiseKit/Alamofire,并且 HTTP 响应以 promise then() 的形式返回,它不能只返回 Void。它需要返回一个 Promise。 我已经用更多的例子更新了我的答案(这些例子已经过测试并且可以工作)。我无法帮助您诊断您的代码,因为我不知道其中一些例程的作用。如果您仍有问题,请通过complete, simple, standalone, reproducible example 更新您的问题。以上是关于从 PromiseKit/Alamofire 返回一个 Promise的主要内容,如果未能解决你的问题,请参考以下文章