从PromiseKit/Alamofire回复承诺

sss*_*ver 2 promise ios swift alamofire promisekit

我试图做这个看似微不足道的事情:

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"))
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,编译器(理所当然地)抱怨说:

'守卫'身体可能不会通过,考虑使用'返回'或'休息'退出范围

我明白我需要在这里回复一个承诺.我只是无法弄清楚究竟要放在reject()和fulfill()调用之下.

Rob*_*Rob 7

没有任何问题rejectfulfill电话.问题是,在您rejectguard陈述中,您还必须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
}
Run Code Online (Sandbox Code Playgroud)

关键点在于,您不希望混淆此方法返回的promise(稍后由fulfillor 满足reject),并且在此闭包内,您必须立即使用returnin guard子句退出闭包.


我无法用你的代码重现这个问题(因为你没有提供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)
                }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,你正在回归a Promise,但在Alamofire关闭中,你只是在退出你的guard陈述.


如果你正在使用PromiseKit/Alamofire并打电话then,你可能想要创建一个可以返回的承诺,例如:

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)
            }
    }
}
Run Code Online (Sandbox Code Playgroud)

或者,如果它太毛茸茸,你可以解析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)
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,无论哪种方式,即使使用PromiseKit/Alamofire,你仍然只是returnguard条款中.

  • 我用几个示例(经过测试和工作)更新了我的答案。我无法帮助您诊断代码,因为我不知道其中一些例程的作用。如果您仍然遇到问题,请使用[完整,简单,独立,可复制的示例](http://stackoverflow.com/help/mcve)更新您的问题。 (2认同)