PromiseKit源码分析

整体思路

链式异步思路 每个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)
                }
            }
        }
}
复制代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值