转载

聊聊 PromiseKit

PromiseKit,来自 Promise 这个的概念,它可以帮助我们的代码变得更加简洁优雅。 我们今天就来聊聊它。

Promise 背景简介

Promise 这个概念之前更多应用于 JavaScript, 主要是为了解决 JavaScript 的 Callback Hell(回调地狱) 问题。 简单来说就是, JS 中很异步函数都是用 callback 的形式返回结果,而开发者经常会连续的使用这些异步调用,最后就导致回调嵌套的层级越来越深,严重影响代码的结构和可读性。

关于 Callback Hell, 还有一个外国朋友专门建立了一个页面 - http://callbackhell.com , 大家有兴趣的话可以了解一下。

Promise 的出现,就是用来解决 Callback Hell 这个问题的。它用线性调用的接口来封装回调嵌套这些问题, 在 JavaScript 中的应用比较广泛。 JS 有一个专门的第三方库就叫做 Promises:

https://www.promisejs.org

PromiseKit

介绍完了背景, 我们就来继续来了解 PromiseKit 吧。 PromiseKit 是专门针对 Swift 和 Objective-C 语言的解决方案。 我们先看看他能用来干什么。

如果用 iOS 原生的接口,我们要弹出一个 UIAlertView 对话框,并处理点击事件的话, 大概需要这样做:

func showAlert() {

let alert = UIAlertView(title: "Title", message: "Msg", delegate: self, cancelButtonTitle: "Cancel", otherButtonTitles: "OK")
alert.show()

}

func alertView(alertView: UIAlertView, clickedButtonAtIndex buttonIndex: Int) {

print("button index /(buttonIndex)")

}

我们先要创建一个 UIAlertView, 然后还要指定它的代理, 如果我们需要一些中间变量的话, 还需要将这些变量声明为类的属性, 以便这两个方法都能从全局来访问。 我们开发 iOS App 的时候,这种情况非常多。

那么咱们再来看看用 PromiseKit 来处理这个问题的方法:

import PromiseKit

func testAlert() {

let alert = UIAlertView(title: "Title", message: "Msg", delegate: nil, cancelButtonTitle: "Cancel", otherButtonTitles: "OK")

alert.promise().then { buttonIndex in

print("ok /(buttonIndex)")

}

}

这次我们没有用任何的代理方法, 而是直接用 PromiseKit 对 UIAlertView 提供的扩展, 在一个方法中将 UIAlertView 的创建和事件处理声明完成。

PromiseKit 对很对 iOS 提供的控件都提供了类似的扩展, 比如 UIActionSheet , NSURLConnection , UIViewController , CLLocationManager 等等。

链式调用

链式调用是 PromiseKit 的核心特性,比如这样的代码:

NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: "http://aaa.cc")!) { data, response, error in

NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: "http://bbb.cc")!) { data, response, error in

NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: "http://ddd.cc")!) { data, response, error in

print("finished")

}

}

}

这个就是 Callback Hell, dataTaskWithURL 方法的回调闭包一级一级的嵌套。 现在我们这个示例中每个闭包没有太多代码量, 但在实际的项目中,往往这些嵌套的闭包中都含有大量的代码,这样就会严重影响我们阅读这些代码。

再来看看 PromiseKit 的处理方式:

NSURLSession.sharedSession().promise(NSURLRequest(URL: NSURL(string: "http://aaa.cc")!)).then { data in

return NSURLSession.sharedSession().promise(NSURLRequest(URL: NSURL(string: "http://bbb.cc")!))

}.then { data in

return NSURLSession.sharedSession().promise(NSURLRequest(URL: NSURL(string: "http://ddd.cc")!))

}.then { data in

print("finished")

}

这个就是 Promise 的处理方式了, 它的每一层闭包中,我们可以再返回一个 Promise 对象,然后本来是层级嵌套的逻辑, 就变成了线性的逻辑了。 当代码量变大的时候, 我们依然能够很方便的分清楚代码的逻辑结构。

when

有些时候,我们可能会依赖于某些异步任务,需要等他们执行完成后,再进行一些操作。 PromiseKit 为我们提供了这样方便的接口, 比如这样:

let req1 = NSURLSession.sharedSession().promise(NSURLRequest(URL: NSURL(string: "http://bbb.cc")!))
let req2 = NSURLSession.sharedSession().promise(NSURLRequest(URL: NSURL(string: "http://ddd.cc")!))

when(req1, req2).then { resp1, resp2 in

}.error { err in

}

PromiseKit 的 when 函数, 会等到 req1 和 req2 两个请求执行完毕后,在执行后面的闭包,如果期间发生错误, error 就会被调用。

结尾

以上就是 PromiseKit 的基本介绍了, 关于它的更多内容,可以参看 Github 主页:

https://github.com/mxcl/PromiseKit

如果你之前有过其他平台 Promise 的使用经验, 相信上手应该不难。 它确实可以让你的代码简单很多,当然至于是否要采用这种风格,也是见仁见智了。这里抛砖引玉,给大家多提供一种选择。

原文  http://www.swiftcafe.io/2016/07/17/promisekit/
正文到此结束
Loading...