Permalink
Browse files

Add DispatchTimeInterval to after() function

While the use of TimeInterval is understandable from the perspective
of maintaining parity with the Objective-C function PMKAfter, it's not
quite as strongly typed as DispatchTimeInterval.  Also, what's really
going on is a dispatch after a deadline and so support for both seconds
and DispatchTimeInterval seem warranted.
  • Loading branch information...
maguro committed Jul 9, 2017
1 parent c82c094 commit 9395635cfb2abc1820f11897ac957f8cc01e03f3
@@ -175,7 +175,7 @@ situations where tasks *must* be done sequentially; animation is a good example.
```swift
let fetches: [Promise<T>] = makeFetches()
let timeout = after(interval: 4)
let timeout = after(seconds: 4)
race(when(fulfilled: fetches).asVoid(), timeout).then {
//
@@ -236,7 +236,7 @@ foo.then {
## Retry / Polling
```swift
func attempt<T>(interdelay: TimeInterval = 2, maxRepeat: Int = 3, source: () -> Promise<T>) -> Promise<T>
func attempt<T>(interdelay: DispatchTimeInterval = .seconds(2), maxRepeat: Int = 3, source: () -> Promise<T>) -> Promise<T>
var attempts = 0
func attempt() -> Promise<T> {
attempts += 1
@@ -7,7 +7,7 @@ import PromiseKit
func promise3() -> Promise<Int> {
return after(interval: 1).then {
return after(seconds: 1).then {
return 3
}
}
View
@@ -4,7 +4,25 @@ import Dispatch
/**
- Returns: A new promise that fulfills after the specified duration.
*/
@available(*, deprecated: 4.3, message: "Use after(seconds:)")
public func after(interval: TimeInterval) -> Promise<Void> {
return after(seconds: interval)
}
/**
- Returns: A new promise that fulfills after the specified duration.
*/
public func after(seconds: TimeInterval) -> Promise<Void> {
return Promise { fulfill, _ in
let when = DispatchTime.now() + seconds
DispatchQueue.global().asyncAfter(deadline: when, execute: fulfill)
}
}
/**
- Returns: A new promise that fulfills after the specified duration.
*/
public func after(interval: DispatchTimeInterval) -> Promise<Void> {
return Promise { fulfill, _ in
let when = DispatchTime.now() + interval
DispatchQueue.global().asyncAfter(deadline: when, execute: fulfill)
@@ -146,7 +146,7 @@ class BridgingTests: XCTestCase {
// AnyPromise.then { return x }
let input = after(interval: 0).then{ 1 }
let input = after(seconds: 0).then{ 1 }
AnyPromise(input).then { obj -> Int in
XCTAssertEqual(obj as? Int, 1)
@@ -164,11 +164,11 @@ class BridgingTests: XCTestCase {
// AnyPromise.then { return AnyPromise }
let input = after(interval: 0).then{ 1 }
let input = after(seconds: 0).then{ 1 }
AnyPromise(input).then { obj -> AnyPromise in
XCTAssertEqual(obj as? Int, 1)
return AnyPromise(after(interval: 0).then{ 2 })
return AnyPromise(after(seconds: 0).then{ 2 })
}.then { obj -> Void in
XCTAssertEqual(obj as? Int, 2)
ex.fulfill()
@@ -182,11 +182,11 @@ class BridgingTests: XCTestCase {
// AnyPromise.then { return Promise<Int> }
let input = after(interval: 0).then{ 1 }
let input = after(seconds: 0).then{ 1 }
AnyPromise(input).then { obj -> Promise<Int> in
XCTAssertEqual(obj as? Int, 1)
return after(interval: 0).then{ 2 }
return after(seconds: 0).then{ 2 }
}.then { value -> Void in
XCTAssertEqual(value, 2)
ex.fulfill()
@@ -200,7 +200,7 @@ class BridgingTests: XCTestCase {
func test4() {
let ex = expectation(description: "")
Promise(value: 1).then { _ -> AnyPromise in
return AnyPromise(after(interval: 0).then{ 1 })
return AnyPromise(after(seconds: 0).then{ 1 })
}.then { x -> Void in
XCTAssertEqual(x as? Int, 1)
ex.fulfill()
@@ -213,7 +213,7 @@ class BridgingTests: XCTestCase {
let ex = expectation(description: "")
Promise(value: 1).then { _ -> AnyPromise in
let promise = after(interval: 0.1).then{ throw Error.dummy }
let promise = after(interval: .milliseconds(100)).then{ throw Error.dummy }
return AnyPromise(promise)
}.catch { err in
ex.fulfill()
@@ -3,7 +3,7 @@ import PromiseKit
// for BridgingTests.m
@objc(PMKPromiseBridgeHelper) class PromiseBridgeHelper: NSObject {
@objc func bridge1() -> AnyPromise {
let p = after(interval: 0.01)
let p = after(interval: .milliseconds(10))
return AnyPromise(p)
}
}
@@ -13,7 +13,7 @@ class CancellationTests: XCTestCase {
ex1.fulfill()
}
after(interval: 0).then { _ in
after(seconds: 0).then { _ in
throw Error.cancel
}.then {
XCTFail()
@@ -28,7 +28,7 @@ class CancellationTests: XCTestCase {
func testThrowCancellableErrorThatIsNotCancelled() {
let expct = expectation(description: "")
after(interval: 0).then {
after(seconds: 0).then {
throw Error.dummy
}.then {
XCTFail()
@@ -49,7 +49,7 @@ class CancellationTests: XCTestCase {
ex2.fulfill()
}
after(interval: 0).then { _ in
after(seconds: 0).then { _ in
throw NSError(domain: PMKErrorDomain, code: PMKOperationCancelled, userInfo: nil)
}.recover(policy: .allErrors) { err -> Void in
ex1.fulfill()
@@ -68,7 +68,7 @@ class CancellationTests: XCTestCase {
func testCatchCancellation() {
let ex = expectation(description: "")
after(interval: 0).then { _ in
after(seconds: 0).then { _ in
throw NSError(domain: PMKErrorDomain, code: PMKOperationCancelled, userInfo: nil)
}.catch(policy: .allErrors) { err in
ex.fulfill()
@@ -98,8 +98,8 @@ class ErrorUnhandlerTests: XCTestCase {
let ex3 = expectation(description: "")
let ex4 = expectation(description: "")
after(interval: 0.1).then { _ -> Void in r(Error.test); ex1.fulfill() }
after(interval: 0.15).then { _ -> Void in r(Error.test); ex2.fulfill() }.always(execute: ex3.fulfill)
after(interval: .milliseconds(100)).then { _ -> Void in r(Error.test); ex1.fulfill() }
after(interval: .milliseconds(150)).then { _ -> Void in r(Error.test); ex2.fulfill() }.always(execute: ex3.fulfill)
p.catch { error in
ex4.fulfill()
@@ -120,7 +120,7 @@ class ErrorUnhandlerTests: XCTestCase {
}
Promise<Void> { _, reject in
after(interval: 0.1).then {
after(interval: .milliseconds(100)).then {
throw Error.test
}.catch(execute: reject)
}
@@ -39,7 +39,7 @@ class ZalgoTests: XCTestCase {
}
var p1: Promise<Void>!
p1 = after(interval: 0.1).then(on: zalgo) { _ -> Promise<Void> in
p1 = after(interval: .milliseconds(100)).then(on: zalgo) { _ -> Promise<Void> in
ex.0.fulfill()
return p1
}
@@ -8,7 +8,15 @@ class AfterTests: XCTestCase {
waitForExpectations(timeout: 2, handler: nil)
let ex2 = expectation(description: "")
__PMKAfter(0).then{ _ in ex2.fulfill() }
after(seconds: 0).then(execute: ex2.fulfill)
waitForExpectations(timeout: 2, handler: nil)
let ex3 = expectation(description: "")
after(interval: .seconds(0)).then(execute: ex3.fulfill)
waitForExpectations(timeout: 2, handler: nil)
let ex4 = expectation(description: "")
__PMKAfter(0).then{ _ in ex4.fulfill() }
waitForExpectations(timeout: 2, handler: nil)
}
@@ -18,7 +26,15 @@ class AfterTests: XCTestCase {
waitForExpectations(timeout: 2, handler: nil)
let ex2 = expectation(description: "")
__PMKAfter(-1).then{ _ in ex2.fulfill() }
after(seconds: -1).then(execute: ex2.fulfill)
waitForExpectations(timeout: 2, handler: nil)
let ex3 = expectation(description: "")
after(interval: .seconds(-1)).then(execute: ex3.fulfill)
waitForExpectations(timeout: 2, handler: nil)
let ex4 = expectation(description: "")
__PMKAfter(-1).then{ _ in ex4.fulfill() }
waitForExpectations(timeout: 2, handler: nil)
}
@@ -28,7 +44,15 @@ class AfterTests: XCTestCase {
waitForExpectations(timeout: 2, handler: nil)
let ex2 = expectation(description: "")
__PMKAfter(1).then{ _ in ex2.fulfill() }
after(seconds: 1).then(execute: ex2.fulfill)
waitForExpectations(timeout: 2, handler: nil)
let ex3 = expectation(description: "")
after(interval: .seconds(1)).then(execute: ex3.fulfill)
waitForExpectations(timeout: 2, handler: nil)
let ex4 = expectation(description: "")
__PMKAfter(1).then{ _ in ex4.fulfill() }
waitForExpectations(timeout: 2, handler: nil)
}
}
@@ -4,7 +4,7 @@ import PromiseKit
class RaceTests: XCTestCase {
func test1() {
let ex = expectation(description: "")
race(after(interval: 0.01).then{ 1 }, after(interval: 1.0).then{ 2 }).then { index -> Void in
race(after(interval: .milliseconds(10)).then{ 1 }, after(seconds: 1).then{ 2 }).then { index -> Void in
XCTAssertEqual(index, 1)
ex.fulfill()
}
@@ -13,7 +13,7 @@ class RaceTests: XCTestCase {
func test2() {
let ex = expectation(description: "")
race(after(interval: 1.0).then{ 1 }, after(interval: 0.01).then{ 2 }).then { index -> Void in
race(after(seconds: 1).then{ 1 }, after(interval: .milliseconds(10)).then{ 2 }).then { index -> Void in
XCTAssertEqual(index, 2)
ex.fulfill()
}
@@ -22,7 +22,7 @@ class RaceTests: XCTestCase {
func test1Array() {
let ex = expectation(description: "")
try! race(promises: [after(interval: 0.01).then{ 1 }, after(interval: 1.0).then{ 2 }]).then { index -> Void in
try! race(promises: [after(interval: .milliseconds(10)).then{ 1 }, after(seconds: 1).then{ 2 }]).then { index -> Void in
XCTAssertEqual(index, 1)
ex.fulfill()
}
@@ -31,7 +31,7 @@ class RaceTests: XCTestCase {
func test2Array() {
let ex = expectation(description: "")
try! race(promises: [after(interval: 1.0).then{ 1 }, after(interval: 0.01).then{ 2 }]).then { index -> Void in
try! race(promises: [after(seconds: 1).then{ 1 }, after(interval: .milliseconds(10)).then{ 2 }]).then { index -> Void in
XCTAssertEqual(index, 2)
ex.fulfill()
}
@@ -14,7 +14,7 @@ class WhenConcurrentTestCase_Swift: XCTestCase {
return nil
}
return after(interval: 0.01).then {
return after(interval: .milliseconds(10)).then {
return number * number
}
}
@@ -64,7 +64,7 @@ class WhenConcurrentTestCase_Swift: XCTestCase {
return nil
}
return after(interval: 0.01).then {
return after(interval: .milliseconds(10)).then {
guard number != 0 else {
return Promise(error: expectedError)
}
@@ -104,7 +104,7 @@ class WhenConcurrentTestCase_Swift: XCTestCase {
return nil
}
return after(interval: 0.01).then {
return after(interval: .milliseconds(10)).then {
currentConcurrently -= 1
return Promise(value: number * number)
}
@@ -106,8 +106,8 @@ class WhenTests: XCTestCase {
enum Error: Swift.Error { case dummy }
let e1 = expectation(description: "")
let p1 = after(interval: 0.1).then{ true }
let p2 = after(interval: 0.2).then{ throw Error.dummy }
let p1 = after(interval: .milliseconds(100)).then{ true }
let p2 = after(interval: .milliseconds(200)).then{ throw Error.dummy }
let p3 = Promise(value: false)
when(fulfilled: p1, p2, p3).catch { _ in
@@ -122,10 +122,10 @@ class WhenTests: XCTestCase {
XCTAssertNil(Progress.current())
let p1 = after(interval: 0.01)
let p2 = after(interval: 0.02)
let p3 = after(interval: 0.03)
let p4 = after(interval: 0.04)
let p1 = after(interval: .milliseconds(10))
let p2 = after(interval: .milliseconds(20))
let p3 = after(interval: .milliseconds(30))
let p4 = after(interval: .milliseconds(40))
let progress = Progress(totalUnitCount: 1)
progress.becomeCurrent(withPendingUnitCount: 1)
@@ -146,10 +146,10 @@ class WhenTests: XCTestCase {
XCTAssertNil(Progress.current())
let p1 = after(interval: 0.01)
let p2: Promise<Void> = after(interval: 0.02).then { throw NSError(domain: "a", code: 1, userInfo: nil) }
let p3 = after(interval: 0.03)
let p4 = after(interval: 0.04)
let p1 = after(interval: .milliseconds(10))
let p2: Promise<Void> = after(interval: .milliseconds(20)).then { throw NSError(domain: "a", code: 1, userInfo: nil) }
let p3 = after(interval: .milliseconds(30))
let p4 = after(interval: .milliseconds(40))
let progress = Progress(totalUnitCount: 1)
progress.becomeCurrent(withPendingUnitCount: 1)
@@ -192,7 +192,7 @@ class WhenTests: XCTestCase {
let ex = expectation(description: "")
let p1 = Promise<Void>(error: Error.test)
let p2 = after(interval: 0.1)
let p2 = after(interval: .milliseconds(100))
when(fulfilled: p1, p2).then{ XCTFail() }.catch { error in
XCTAssertTrue(error as? Error == Error.test)
ex.fulfill()
@@ -216,16 +216,16 @@ class WhenTests: XCTestCase {
let ex3 = expectation(description: "")
let p1 = Promise<Void>(error: Error.test)
let p2 = after(interval: 0.1).then { throw Error.straggler }
let p3 = after(interval: 0.2).then { throw Error.straggler }
let p2 = after(interval: .milliseconds(100)).then { throw Error.straggler }
let p3 = after(interval: .milliseconds(200)).then { throw Error.straggler }
when(fulfilled: p1, p2, p3).catch { error -> Void in
XCTAssertTrue(Error.test == error as? Error)
ex1.fulfill()
}
p2.always { after(interval: 0.1).then(execute: ex2.fulfill) }
p3.always { after(interval: 0.1).then(execute: ex3.fulfill) }
p2.always { after(interval: .milliseconds(100)).then(execute: ex2.fulfill) }
p3.always { after(interval: .milliseconds(100)).then(execute: ex3.fulfill) }
waitForExpectations(timeout: 1, handler: nil)
}
@@ -81,7 +81,7 @@ class PromiseTupleTests: XCTestCase {
func testThenNtuplePromisesFail(generator: (Promise<Void>, Promise<Any>, Promise<Any>) -> Promise<Void>) {
let ex = expectation(description: "")
generator(after(interval: 0.1), Promise<Any>(value: 1), Promise<Any>(error: TestError.sthWrong)).then {
generator(after(interval: .milliseconds(100)), Promise<Any>(value: 1), Promise<Any>(error: TestError.sthWrong)).then {
XCTFail("Then called instead of `catch`")
}.catch { e in
if case TestError.sthWrong = e {
@@ -219,7 +219,7 @@ class PromiseTupleTests: XCTestCase {
func testFirstlyNtuplePromisesFail(generator: (Promise<Void>, Promise<Any>, Promise<Any>) -> Promise<Void>) {
let ex = expectation(description: "")
generator(after(interval: 0.1), Promise<Any>(value: 1), Promise<Any>(error: TestError.sthWrong)).then {
generator(after(interval: .milliseconds(100)), Promise<Any>(value: 1), Promise<Any>(error: TestError.sthWrong)).then {
XCTFail("Then called instead of `catch`")
}.catch { e in
if case TestError.sthWrong = e {
@@ -262,10 +262,10 @@ fileprivate enum TestError: Error {
}
fileprivate func getPromises(callback: ((Promise<Bool>, Promise<Int>, Promise<String>, Promise<(Int, Int)>, Promise<Double>, Promise<Void>)) -> Void) {
let boolean = after(interval: 0.1).then { true }
let boolean = after(interval: .milliseconds(100)).then { true }
let integer = Promise(value: 1)
let string = Promise(value: "success")
let integerTuple = after(interval: 0.1).then { (2, 3) }
let integerTuple = after(interval: .milliseconds(100)).then { (2, 3) }
let double = Promise(value: 0.1)
let empty = Promise(value: ())
callback(boolean, integer, string, integerTuple, double, empty)

0 comments on commit 9395635

Please sign in to comment.