整体思路
链式异步思路 每个Promise中保存下一个Promise的执行逻辑并把当前操作返回值传递给下一个Promise,已经执行的seal状态变成.resolved,没有就加到.pendding(handlers)中handlers的bodies里面等待执行,下一个promise根据上一个promise的state状态来进行下一步,把自己的处理流程加到上一个promise处理流程的后面
每个promise实例通过state: State<T> 保存当前promise的状态
seal表示当前是否已经执行
- .panding表示没有执行,正在等待执行
- .resolved表示已经完成,并且保存了返回值
fulfill履行
reject拒绝
then成功时调用
catch失败时调用
State.swift
两个重要的枚举
Seal是用来保存处理状态
enum Seal<T> {
case pending(Handlers<T>) // 等待处理,Handlers用来保存当前promise下一个处理流程
case resolved(Resolution<T>)// 已经处理有返回值,Resolution封装正确和错误的返回值
}
复制代码
Resolution封装返回值
enum Resolution<T> {
case fulfilled(T) // 正确的返回值
case rejected(Error, ErrorConsumptionToken) // 错误的返回值
init(_ error: Error) {
self = .rejected(error, ErrorConsumptionToken(error))
}
}
复制代码
Handlers用来保存当前promise下一个处理流程,bodies保存的闭包就是接下来要处理的逻辑
class Handlers<T>: Sequence {
var bodies: [(Resolution<T>) -> Void] = []
func append(_ body: @escaping (Resolution<T>) -> Void) {
bodies.append(body)
}
func makeIterator() -> IndexingIterator<[(Resolution<T>) -> Void]> {
return bodies.makeIterator()
}
var count: Int {
return bodies.count
}
}
复制代码
seal属性:用来保存处理状态
seal是在以下闭包中改变
required init(resolver: inout ((Resolution<T>) -> Void)!) {
seal = .pending(Handlers<T>())
super.init()
// 闭包的实现
resolver = { resolution in
var handlers: Handlers<T>?
self.barrier.sync(flags: .barrier) {
if case .pending(let hh) = self.seal {
self.seal = .resolved(resolution)
handlers = hh
}
}
if let handlers = handlers {
for handler in handlers {
handler(resolution)
}
}
}
}
复制代码
pipe方法根据seal的状态来判断是立即返回还是稍后处理
final func pipe(_ body: @escaping (Resolution<T>) -> Void) {
get { seal in
switch seal {
case .pending(let handlers):
handlers.append(body)
case .resolved(let resolution):
body(resolution)
}
}
}
复制代码
Promise.swift
state: State<T> 保存当前promise的状态
初始化方法1,第一个promise初始化调用此方法,根据外面调用fulfill或者reject,来更新state属性
required public init(resolvers: (_ fulfill: @escaping (T) -> Void, _ reject: @escaping (Error) -> Void) throws -> Void) {
var resolve: ((Resolution<T>) -> Void)!
do {
state = UnsealedState(resolver: &resolve)
try resolvers({ resolve(.fulfilled($0)) }, { error in
#if !PMKDisableWarnings
if self.isPending {
resolve(Resolution(error))
} else {
NSLog("PromiseKit: warning: reject called on already rejected Promise: \(error)")
}
#else
resolve(Resolution(error))
#endif
})
} catch {
resolve(Resolution(error))
}
}
复制代码
初始化方法2,由Promise.then调用,在链式语法中自动初始化
init(sealant: (@escaping (Resolution<T>) -> Void) -> Void) {
var resolve: ((Resolution<T>) -> Void)!
state = UnsealedState(resolver: &resolve)
sealant(resolve)
}
复制代码
then方法,调用初始化方法2进行下一个promise的初始化
public func then<U>(on q: DispatchQueue = .default, execute body: @escaping (T) throws -> U) -> Promise<U> {
return Promise<U> { resolve in
state.then(on: q, else: resolve) { value in
resolve(.fulfilled(try body(value)))
}
}
}
复制代码
代码逻辑分析
分析以下代码调用逻辑
API.getHomeInfo().then { res in
print(res)
}.catch { (error) in
print(error)
}
复制代码
API.getHomeInfo()初始化一个promise,state保存了promise的状态,当调用fulfill或者reject的时候,就会调用state中resolver闭包的实现,将seal的状态从.pending变成.resolved,并将值传递给.resolved,将.pending中Handlers取出,将值传递给Handlers的bodies闭包数组来执行
return Promise<T> { fulfill, reject in
requestByIgnoringCodeEvent(config) { (requestResult) in
if requestResult.isSuccess {
fulfill(requestResult)
} else {
let message = requestResult.message ?? "服务器返回错误"
let error = NSError(domain: "Network Error", code: 1,
userInfo: [NSLocalizedDescriptionKey: message])
reject(error)
}
}
}
复制代码
then也是初始化一个promise实例,调用初始化方法2,将state中resolve闭包传递到外面来根据上一个promise的state.then来进行进行操作
public func then<U>(on q: DispatchQueue = .default, execute body: @escaping (T) throws -> U) -> Promise<U> {
return Promise<U> { resolve in
state.then(on: q, else: resolve) { value in
resolve(.fulfilled(try body(value)))
}
}
}
复制代码
state.then调用的pipe函数
pipe函数调用get函数
get函数先判断seal的状态,如果当前promise没有调用fullfill或者reject,说明还没有返回值过来,那seal的状态就还是.pending就线程就等待前面的完成,有返回值seal状态就变成了.resolved,最后将seal状态传递闭包
pipe函数处理get函数传递给来的seal状态,.pending就接受的闭包添加到handlers的bidies数组里面,后面合适的时候在执行闭包,如果是.resolved就直接把.resolved中值传递给闭包参数
final func then<U>(on q: DispatchQueue, else rejecter: @escaping (Resolution<U>) -> Void, execute body: @escaping (T) throws -> Void) {
pipe { resolution in
switch resolution {
case .fulfilled(let value):
contain_zalgo(q, rejecter: rejecter) {
// 触发下个流程的开始
try body(value)
}
case .rejected(let error, let token):
rejecter(.rejected(error, token))
}
}
}
final func pipe(_ body: @escaping (Resolution<T>) -> Void) {
get { seal in
switch seal {
case .pending(let handlers):
handlers.append(body)
case .resolved(let resolution):
body(resolution)
}
}
}
override func get(body: @escaping (Seal<T>) -> Void) {
var sealed = false
barrier.sync {
switch self.seal {
case .resolved:
sealed = true
case .pending:
sealed = false
}
}
if !sealed {
barrier.sync(flags: .barrier) {
switch (self.seal) {
case .pending:
body(self.seal)
case .resolved:
sealed = true // welcome to race conditions
}
}
}
if sealed {
body(seal) // as much as possible we do things OUTSIDE the barrier_sync
}
}
复制代码
then函数处理pipe函数传递过来的返回值,正常调用body(value),异常调用rejecter(.rejected(error, token))
promise.then函数处理state.then传递过来的参数,在回调promise的state中初始化的闭包,更新state中seal的状态
resolver = { resolution in
var handlers: Handlers<T>?
self.barrier.sync(flags: .barrier) {
if case .pending(let hh) = self.seal {
self.seal = .resolved(resolution)
handlers = hh
}
}
if let handlers = handlers {
for handler in handlers {
handler(resolution)
}
}
}
复制代码
catch逻辑
promise.catch调用state.catch
state.catch调用pipe函数
pipe函数调用get函数
get函数在进行状态判断,返回当前self.seal状态
pipe函数处理get返回的seal状态,判断为.pending,将body添加到handlers的bodies数组中稍后处理,上一步在更新state中seal状态时候,会将.pending中handles中的bodies数组拿出来运行,这个时候就会执行state.catch方法传入的闭包
promise.catch函数处理state.catch返回的参数,正确就不执行,错误执行body闭包,body就是自己写的错误处理逻辑
// Promise中的catch方法
@discardableResult
public func `catch`(on q: DispatchQueue = .default, policy: CatchPolicy = .allErrorsExceptCancellation, execute body: @escaping (Error) -> Void) -> Promise {
state.catch(on: q, policy: policy, else: { _ in }, execute: body)
return self
}
// State中的catch方法
final func `catch`(on q: DispatchQueue, policy: CatchPolicy, else resolve: @escaping (Resolution<T>) -> Void, execute body: @escaping (Error) throws -> Void) {
pipe { resolution in
switch (resolution, policy) {
case (.fulfilled, _):
resolve(resolution)
case (.rejected(let error, _), .allErrorsExceptCancellation) where error.isCancelledError:
resolve(resolution)
case (let .rejected(error, token), _):
contain_zalgo(q, rejecter: resolve) {
token.consumed = true
try body(error)
}
}
}
}
复制代码