Skip to content

Commit

Permalink
Add discard, always, and defer method
Browse files Browse the repository at this point in the history
  • Loading branch information
davidask committed Jan 10, 2019
1 parent f87ff5e commit 1c3839e
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 14 deletions.
15 changes: 6 additions & 9 deletions Futures.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -129,12 +129,12 @@
B757AE7120B8A5BA00850F92 /* Sources */ = {
isa = PBXGroup;
children = (
B757AE7220B8A5BA00850F92 /* Future */,
B757AE7220B8A5BA00850F92 /* Futures */,
);
path = Sources;
sourceTree = "<group>";
};
B757AE7220B8A5BA00850F92 /* Future */ = {
B757AE7220B8A5BA00850F92 /* Futures */ = {
isa = PBXGroup;
children = (
B757AE7320B8A5BA00850F92 /* FutureResult.swift */,
Expand All @@ -144,15 +144,14 @@
B79FF3B620BC6E34001A625C /* AnyFuture.swift */,
B768073720C6C02E00402ECB /* FutureProvider.swift */,
);
name = Future;
path = Futures;
sourceTree = "<group>";
};
B757AE8220B8A5C700850F92 /* Framework */ = {
isa = PBXGroup;
children = (
B757AE8320B8A5C700850F92 /* FutureTests */,
B757AE8520B8A5C700850F92 /* Future */,
B757AE8520B8A5C700850F92 /* Futures */,
);
path = Framework;
sourceTree = "<group>";
Expand All @@ -166,30 +165,28 @@
path = FuturesTests;
sourceTree = "<group>";
};
B757AE8520B8A5C700850F92 /* Future */ = {
B757AE8520B8A5C700850F92 /* Futures */ = {
isa = PBXGroup;
children = (
B757AE8620B8A5C700850F92 /* Futures.h */,
B757AE8720B8A5C700850F92 /* Info.plist */,
);
name = Future;
path = Futures;
sourceTree = "<group>";
};
B757AE8C20B8A60600850F92 /* Tests */ = {
isa = PBXGroup;
children = (
B757AE8E20B8A60600850F92 /* FutureTests */,
B757AE8E20B8A60600850F92 /* FuturesTests */,
);
path = Tests;
sourceTree = "<group>";
};
B757AE8E20B8A60600850F92 /* FutureTests */ = {
B757AE8E20B8A60600850F92 /* FuturesTests */ = {
isa = PBXGroup;
children = (
B757AE8F20B8A60600850F92 /* FuturesTests.swift */,
);
name = FutureTests;
path = FuturesTests;
sourceTree = "<group>";
};
Expand Down
55 changes: 50 additions & 5 deletions Sources/Futures/Future.swift
Original file line number Diff line number Diff line change
Expand Up @@ -466,15 +466,15 @@ public extension Future {
/// Note that the provided callback is called regardless of whether this future is fulfilled or rejected.
/// The returned `Future<T>` is fulfilled **only** if this and the provided future both are fullfilled.
///
/// In essence, the returned future will forward the result of this future, if the provided future
/// In short, the returned future will forward the result of this future, if the provided future
/// is fulfilled.
///
/// - Parameters:
/// - queue: Dispatch queue to observe on.
/// - initialResult: An initial result to begin the reduction.
/// - callback: A callback that returns a `Future<Void>` to be deferred.
/// - Returns: A future that will receive the eventual value.
func `defer`(on queue: DispatchQueue = .futures, callback: @escaping () -> Future<Void>) -> Future<T> {
func always(on queue: DispatchQueue = .futures, callback: @escaping () -> Future<Void>) -> Future<T> {
let promise = Promise<T>()

whenResolved(on: queue) { result1 in
Expand All @@ -497,6 +497,29 @@ public extension Future {
return promise.future
}

/// Returns a new `Future<T>` that will resolve with the result of this `Future` **after** the provided callback
/// runs.
///
/// Note that the provided callback is called regardless of whether this future is fulfilled or rejected.
///
/// This method is useful for times you want to execute code at the end of a chain of operations, regarless
/// of whether successful or not.
///
/// - Parameters:
/// - queue: Dispatch queue to observe on.
/// - callback: Callback to run.
/// - Returns: A future that will receive the eventual value.
func `defer`(on queue: DispatchQueue = .futures, callback: @escaping () -> Void) -> Future<T> {
let promise = Promise<T>()

whenResolved(on: queue) { result in
callback()
promise.resolve(result)
}

return promise.future
}

enum PollError: Error {
case retryCountExceeded
}
Expand All @@ -507,14 +530,14 @@ public extension Future {
/// is acceptable.
///
/// - Parameters:
/// - dispatchQueue: Dispatch queue to poll on,
/// - queue: Dispatch queue to poll on,
/// - future: Future used as the polling function.
/// - interval: Time to wait between invoking subsequent futures.
/// - retryCount: maxRetryCount Maximum number of times to invoke the supplied future
/// - finished: Handler to invoke, resolving whether the result of the given promise is acceptable
/// - Returns: A future that will receive the eventual value.
static func poll<T>(
on dispatchQueue: DispatchQueue = .futures,
on queue: DispatchQueue = .futures,
future: @escaping @autoclosure () -> Future<T>,
interval: TimeInterval,
maxRetryCount: Int,
Expand All @@ -534,7 +557,7 @@ public extension Future {
if finished(value) {
promise.fulfill(value)
} else if numberOfRetries < maxRetryCount {
dispatchQueue.asyncAfter(deadline: .now() + (numberOfRetries < 1 ? 0 : interval)) {
queue.asyncAfter(deadline: .now() + (numberOfRetries < 1 ? 0 : interval)) {
poll()
}
} else {
Expand All @@ -551,6 +574,28 @@ public extension Future {

return promise.future
}

/// Returns a new Future<Void>, effectively discarding the result of the caller.
///
/// This method is useful when the value of a future is of no consequence.
///
/// - Parameter queue: Dispatch queue to discard on.
/// - Returns: A future that will receive the eventual value.
@discardableResult
func discard(on queue: DispatchQueue = .futures) -> Future<Void> {

let promise = Promise<Void>()

whenFulfilled(on: queue) { _ in
promise.fulfill()
}

whenRejected { error in
promise.reject(error)
}

return promise.future
}
}

public extension Future {
Expand Down

0 comments on commit 1c3839e

Please sign in to comment.