// // 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(_ block: @escaping (T) -> X) -> Promise { let p = registerThen(block) tryStartInitialPromiseAndStartIfneeded() return p } @discardableResult public func registerThen(_ block: @escaping (T) -> X) -> Promise { let p = Promise() 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(_ block: @escaping (T) -> Promise) -> Promise { tryStartInitialPromiseAndStartIfneeded() return registerThen(block) } @discardableResult public func registerThen(_ block: @escaping (T) -> Promise) -> Promise { let p = Promise() 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(_ promise: Promise) -> Promise { return then { _ in promise } } @discardableResult public func registerThen(_ promise: Promise) -> Promise { return registerThen { _ in promise } } fileprivate func registerNextPromise(_ block: (T) -> Promise, result: T, resolve: @escaping (X) -> Void, reject: @escaping ((Error) -> Void)) { let nextPromise: Promise = block(result) nextPromise.then { x in resolve(x) }.onError(reject) } }