diff --git a/Sources/Pwomise/Pwomise.swift b/Sources/Pwomise/Pwomise.swift index 45d1a2c..4900c95 100644 --- a/Sources/Pwomise/Pwomise.swift +++ b/Sources/Pwomise/Pwomise.swift @@ -7,12 +7,36 @@ public protocol PromiseConvertible { var asPromise: Promise { get } } +public enum PromiseInconsistencyError: Error { + case emptyArray +} + public class Promise: CustomDebugStringConvertible { internal typealias Pending = PendingPromise public typealias Completion = Result public typealias Resolve = (Output) -> () public typealias Reject = (Error) -> () + public static func any(_ promises: [Promise]) -> Promise { + guard promises.count > 0 else { + return .failure(PromiseInconsistencyError.emptyArray) + } + + let superPromise = Promise() + + for promise in promises { + promise.always { completion in + guard superPromise.pending else { + return + } + + superPromise.result = .resolved(completion) + } + } + + return superPromise + } + public static func all(_ promises: [Promise]) -> Promise<[Output]> { guard promises.count > 0 else { return .success([]) diff --git a/Tests/PwomiseTests/PwomiseTests.swift b/Tests/PwomiseTests/PwomiseTests.swift index d1b76d3..2450b26 100644 --- a/Tests/PwomiseTests/PwomiseTests.swift +++ b/Tests/PwomiseTests/PwomiseTests.swift @@ -2,5 +2,20 @@ @testable import Pwomise final class PwomiseTests: XCTestCase { - + func testRace() { + var fulfilled = false + + Promise.any([ + Promise { resolve, reject in + resolve(()) + }, + Promise { resolve, reject in + resolve(()) + } + ]).then { _ in + XCTAssert(!fulfilled, "resolved multiple times") + + fulfilled = true + } + } }