Skip to content

Commit

Permalink
Change timeout's default context to .nowOr(.auto)
Browse files Browse the repository at this point in the history
This change means the returned promise will already be resolved if the
receiver was already resolved, otherwise it behaves the same.

Fixes #50.
  • Loading branch information
lilyball committed May 22, 2020
1 parent 9939ad5 commit 178b6cf
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 6 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -419,9 +419,12 @@ Unless you explicitly state otherwise, any contribution intentionally submitted
- Add `Promise.Resolver.hasRequestedCancel` (`TWLResolver.cancelRequested` in Obj-C) that returns `true` if the promise has been requested to
cancel or is already cancelled, or `false` if it hasn't been requested to cancel or is fulfilled or rejected. This can be used when a promise initializer takes
significant time in a manner not easily interrupted by an `onRequestCancel` handler ([#47][]).
- Change `Promise.timeout`'s default context from `.auto` to `.nowOr(.auto)`. This behaves the same as `.auto` in most cases, except if the receiver has
already been resolved this will cause the returned promise to likewise already be resolved ([#50][]).

[#34]: https://github.com/lilyball/Tomorrowland/issues/34 "Add a .mainImmediate context"
[#47]: https://github.com/lilyball/Tomorrowland/issues/47 "Add Promise.Resolver.isCancelled property"
[#50]: https://github.com/lilyball/Tomorrowland/issues/50 "Consider changing timeout's default context to .nowOr(.auto)"

### v1.1.1

Expand Down
10 changes: 7 additions & 3 deletions Sources/ObjC/TWLUtilities.h
Original file line number Diff line number Diff line change
Expand Up @@ -212,9 +212,13 @@ NS_ASSUME_NONNULL_BEGIN
/// the receiver is rejected, the returned promise will be rejected with a \c TWLTimeoutError where
/// the \c .rejectedError property contains the underlying promise's rejection value.
///
/// \note This method assumes a context of <tt>.automatic</tt>, which evaluates to \c .main when
/// invoked on the main thread, otherwise <tt>.defaultQoS</tt>. If you want to specify the context,
/// use \c -timeoutOnContext:withDelay: instead.
/// \note This method assumes a context of <tt>[TWLContext nowOrContext:TWLContext.automatic]</tt>,
/// where \c .automatic evaluates to \c .main when invoked on the main thread, otherwise
/// <tt>.defaultQoS</tt>. The usage of \c +nowOrContext: here means that if the receiver has already
/// been resolved when this method is called, the returned promise will likewise already be
/// resolved. If the receiver has not already resolved then this behaves the same as passing
/// <tt>.automatic</tt>. If you want to specify the context, use \c -timeoutOnContext:withDelay:
/// instead.
///
/// \param delay The delay before the returned promise times out. If less than or equal to zero, the
/// returned promise will be timed out at once unless the receiver is already resolved.
Expand Down
2 changes: 1 addition & 1 deletion Sources/ObjC/TWLUtilities.m
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ - (TWLPromise *)delay:(NSTimeInterval)delay onContext:(TWLContext *)context {
}

- (TWLPromise *)timeoutWithDelay:(NSTimeInterval)delay {
return [self timeoutOnContext:TWLContext.automatic withDelay:delay];
return [self timeoutOnContext:[TWLContext nowOrContext:TWLContext.automatic] withDelay:delay];
}

- (TWLPromise *)timeoutOnContext:(TWLContext *)context withDelay:(NSTimeInterval)delay {
Expand Down
8 changes: 6 additions & 2 deletions Sources/Utilities.swift
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,11 @@ extension Promise {
/// `PromiseTimeoutError.rejected(error)`.
///
/// - Parameter context: The context to invoke the callback on. If not provided, defaults to
/// `.auto`, which evaluates to `.main` when invoked on the main thread, otherwise `.default`.
/// `.nowOr(.auto)`, which evaluates to `.nowOr(.main)` when invoked on the main thread,
/// otherwise `.nowOr(.default)`. The usage of `.nowOr` here means that if the receiver has
/// already been resolved when this method is called, the returned promise will likewise
/// already be resolved. If the receiver has not already resolved then this behaves the same
/// as passing `.auto`.
///
/// If the promise times out, the returned promise will be rejected using the same context. In
/// this event, `.immediate` is treated the same as `.auto`. If provided as `.operationQueue`
Expand All @@ -179,7 +183,7 @@ extension Promise {
/// zero, the returned `Promise` will be timed out at once unless the receiver is already
/// resolved.
/// - Returns: A new `Promise`.
public func timeout(on context: PromiseContext = .auto, delay: TimeInterval) -> Promise<Value,PromiseTimeoutError<Error>> {
public func timeout(on context: PromiseContext = .nowOr(.auto), delay: TimeInterval) -> Promise<Value,PromiseTimeoutError<Error>> {
let (promise, resolver) = Promise<Value,PromiseTimeoutError<Error>>.makeWithResolver()
let propagateCancelBlock = TWLOneshotBlock(block: { [weak _box] in
_box?.propagateCancel()
Expand Down
9 changes: 9 additions & 0 deletions Tests/ObjC/TWLUtilityTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,15 @@ - (void)testTimeoutUsingNowOrContext {
[self waitForExpectations:@[expectation] timeout:0.5];
}

- (void)testTimeoutAlreadyResolvedWithDefaultContext {
// timeout on an already-resolved promise when using the default context should return an
// already-resolved promise.
__auto_type promise = [[TWLPromise<NSNumber*,NSString*> newFulfilledWithValue:@42] timeoutWithDelay:0.05];
NSNumber *value;
XCTAssertTrue([promise getValue:&value error:NULL]);
XCTAssertEqualObjects(value, @42);
}

// MARK: -

- (void)testInitFulfilledAfter {
Expand Down
7 changes: 7 additions & 0 deletions Tests/UtilityTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -654,6 +654,13 @@ final class UtilityTests: XCTestCase {
wait(for: [expectation], timeout: 0.5)
}

func testTimeoutAlreadyResolvedWithDefaultContext() {
// timeout on an already-resolved promise when using the default context should return an
// already-resolved promise.
let promise = Promise<Int,String>(fulfilled: 42).timeout(delay: 0.05)
XCTAssertEqual(promise.result, PromiseResult.value(42))
}

// MARK: -

func testInitFulfilledAfter() {
Expand Down

0 comments on commit 178b6cf

Please sign in to comment.