优雅地处理一连串异步事件--PromiseKit
在平时的开发中,我们会将一些费时的操作放在异步线程中,我们通常会使用闭包或者block来进行回调,如果是一个异步,事件我们通常会写一个回调,多个异步事件就需要写多个回调。可能这多个异步事件存在依赖关系,那就需要将多个闭包嵌套在一起。
比如,
(1)一个电商项目的首页是由main_API来请求多个子模块API,在每个子模块完成请求之后,又需要获取所有子模块中所有商品价格,在整个网络请求流程走完后才能显示首页的内容。
(2)一个提交订单界面:根据商品id获取详细信息,根据用户信息获取默认地址、获取优惠券、获取礼品卡。
(3)一个发红包的流程:检测用户状态是否正常,验证密码,验证手机验证码,获取红包信息。
checkNetwork { (result) in
self.updateUserInfo(block: { (result) in
self.downloadUserInfo(block: { (result) in
self.decoderJSON(block: { (result) in
})
})
})
}
待解决的问题:
- 按照顺序执行多个异步事件
- 多个异步事件完成后再进行下一个事件
使用PromiseKit模式
Promise简化了异步编程,可以创建简洁的函数链,避免了"回调地狱",使得代码变得简洁、易读。
Promise的编写程序的方式,使代码运行起来像是自上而下的效果,并且鼓励使用try\catch来处理报错,可以统一处理错误。
按照顺序执行多个异步事件
使用闭包的方式,整体的感觉还行,但是层级关系越深,其结构就越靠右边,形成一个金字塔的形状,这在JS中叫做回调陷阱(Callback Hell),最终会造成代码可读性降低,代码的复用性降低。
使用PromiseKit的方式
/*
1、检测网络是否正常
2、根据手机号码登录获取token
3、获取用户的数据
4、解析用户的数据
*/
firstly {
self.checkNetwork()
}.then { (bool) -> Promise<String> in
return self.updateUserInfo()
}.then { (token) -> Promise<[String: Any]> in
return self.downloadUserInfo()
}.then { (json) -> Promise<UserModel> in
return self.decoderJSON()
}.done { (userModel) in
print("done")
}.ensure {
print("ensure")
}.catch { (error) in
print("error")
}.finally {
print("finally")
}
-
利用swift特性:函数中如果最后一个参数是函数,那么就可以形成尾随闭包。
-
我们可以看到这形成一个promise链,一个任务引导着另一个任务,一个promise链是自上而下,一个一个执行每个任务直到链的最末端。
-
由Promise函数返回一个promise对象,链中每一个任务都会返回一个promise(promise,我们可以简单的认为是一个异步任务的预期值,比如,一个updateUserInfo()函数返回一个promise,这个promise代表用户的凭证)
-
每一个promise都可以使用then方法来连接
-
当链中的一个事件出现错误,就会停止执行下面的任务,并从catch出来。
多个异步事件完成后再进行下一个事件
/*
1、检测网络是否正常 && 检测服务器是否挂了
2、根据手机号码登录获取token
3、获取用户的数据
4、解析用户的数据
*/
firstly {
when(resolved: self.checkNetwork(), self.checkServerNetwork())
}.then { (bool) -> Promise<String> in
return self.updateUserInfo()
}.then { (token) -> Promise<[String: Any]> in
return self.downloadUserInfo()
}.then { (json) -> Promise<UserModel> in
return self.decoderJSON()
}.ensure {
print("ensure")
}.done { (userModel) in
print("done")
}.catch { (error) in
print("error")
}.finally {
print("finally")
}
每一个任务之间都需要信息共享解决方案:局部变量。