You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

92 lines
3.1 KiB

//
// Promise+Then.swift
// then
//
// Created by Sacha Durand Saint Omer on 20/02/2017.
// Copyright © 2017 s4cha. All rights reserved.
//
import Foundation
public extension Promise {
@discardableResult public func then<X>(_ block: @escaping (T) -> X) -> Promise<X> {
let p = registerThen(block)
tryStartInitialPromiseAndStartIfneeded()
return p
}
@discardableResult public func registerThen<X>(_ block: @escaping (T) -> X) -> Promise<X> {
let p = Promise<X>()
synchronize { state, blocks in
switch state {
case let .fulfilled(value):
let x: X = block(value)
p.fulfill(x)
case let .rejected(error):
p.reject(error)
case .dormant, .pending:
blocks.success.append({ t in
p.fulfill(block(t))
})
blocks.fail.append({ e in
p.reject(e)
})
blocks.progress.append({ f in
p.setProgress(f)
})
}
}
passAlongFirstPromiseStartFunctionAndStateTo(p)
return p
}
@discardableResult public func then<X>(_ block: @escaping (T) -> Promise<X>) -> Promise<X> {
tryStartInitialPromiseAndStartIfneeded()
return registerThen(block)
}
@discardableResult public func registerThen<X>(_ block: @escaping (T) -> Promise<X>)
-> Promise<X> {
let p = Promise<X>()
synchronize { state, blocks in
switch state {
case let .fulfilled(value):
registerNextPromise(block, result: value,
resolve: p.fulfill, reject: p.reject)
case let .rejected(error):
p.reject(error)
case .dormant, .pending:
blocks.success.append({ [weak self] t in
self?.registerNextPromise(block, result: t, resolve: p.fulfill,
reject: p.reject)
})
blocks.fail.append(p.reject)
blocks.progress.append(p.setProgress)
}
}
p.start()
passAlongFirstPromiseStartFunctionAndStateTo(p)
return p
}
@discardableResult public func then<X>(_ promise: Promise<X>) -> Promise<X> {
return then { _ in promise }
}
@discardableResult public func registerThen<X>(_ promise: Promise<X>) -> Promise<X> {
return registerThen { _ in promise }
}
fileprivate func registerNextPromise<X>(_ block: (T) -> Promise<X>,
result: T,
resolve: @escaping (X) -> Void,
reject: @escaping ((Error) -> Void)) {
let nextPromise: Promise<X> = block(result)
nextPromise.then { x in
resolve(x)
}.onError(reject)
}
}