Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 146a7bd

Browse files
committedDec 10, 2015
Merge pull request #51 from ReactKit/on-success-failure
2 parents d9f2191 + 96d6c13 commit 146a7bd

File tree

3 files changed

+124
-22
lines changed

3 files changed

+124
-22
lines changed
 

‎SwiftTask/SwiftTask.swift

Lines changed: 72 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -114,17 +114,17 @@ public class Task<Progress, Value, Error>: Cancellable, CustomStringConvertible
114114
}
115115

116116
///
117-
/// Creates a new task.
117+
/// Create a new task.
118118
///
119119
/// - e.g. Task<P, V, E>(weakified: false, paused: false) { progress, fulfill, reject, configure in ... }
120120
///
121-
/// - parameter weakified: Weakifies progress/fulfill/reject handlers to let player (inner asynchronous implementation inside `initClosure`) NOT CAPTURE this created new task. Normally, `weakified = false` should be set to gain "player -> task" retaining, so that task will be automatically deinited when player is deinited. If `weakified = true`, task must be manually retained somewhere else, or it will be immediately deinited.
121+
/// - Parameter weakified: Weakifies progress/fulfill/reject handlers to let player (inner asynchronous implementation inside `initClosure`) NOT CAPTURE this created new task. Normally, `weakified = false` should be set to gain "player -> task" retaining, so that task will be automatically deinited when player is deinited. If `weakified = true`, task must be manually retained somewhere else, or it will be immediately deinited.
122122
///
123-
/// - parameter paused: Flag to invoke `initClosure` immediately or not. If `paused = true`, task's initial state will be `.Paused` and needs to `resume()` in order to start `.Running`. If `paused = false`, `initClosure` will be invoked immediately.
123+
/// - Parameter paused: Flag to invoke `initClosure` immediately or not. If `paused = true`, task's initial state will be `.Paused` and needs to `resume()` in order to start `.Running`. If `paused = false`, `initClosure` will be invoked immediately.
124124
///
125-
/// - parameter initClosure: e.g. { progress, fulfill, reject, configure in ... }. `fulfill(value)` and `reject(error)` handlers must be called inside this closure, where calling `progress(progressValue)` handler is optional. Also as options, `configure.pause`/`configure.resume`/`configure.cancel` closures can be set to gain control from outside e.g. `task.pause()`/`task.resume()`/`task.cancel()`. When using `configure`, make sure to use weak modifier when appropriate to avoid "task -> player" retaining which often causes retain cycle.
125+
/// - Parameter initClosure: e.g. { progress, fulfill, reject, configure in ... }. `fulfill(value)` and `reject(error)` handlers must be called inside this closure, where calling `progress(progressValue)` handler is optional. Also as options, `configure.pause`/`configure.resume`/`configure.cancel` closures can be set to gain control from outside e.g. `task.pause()`/`task.resume()`/`task.cancel()`. When using `configure`, make sure to use weak modifier when appropriate to avoid "task -> player" retaining which often causes retain cycle.
126126
///
127-
/// - returns: New task.
127+
/// - Returns: New task.
128128
///
129129
public init(weakified: Bool, paused: Bool, initClosure: InitClosure)
130130
{
@@ -141,7 +141,7 @@ public class Task<Progress, Value, Error>: Cancellable, CustomStringConvertible
141141
}
142142

143143
///
144-
/// creates a new task without weakifying progress/fulfill/reject handlers
144+
/// Create a new task without weakifying progress/fulfill/reject handlers
145145
///
146146
/// - e.g. Task<P, V, E>(paused: false) { progress, fulfill, reject, configure in ... }
147147
///
@@ -151,7 +151,7 @@ public class Task<Progress, Value, Error>: Cancellable, CustomStringConvertible
151151
}
152152

153153
///
154-
/// creates a new task without weakifying progress/fulfill/reject handlers (non-paused)
154+
/// Create a new task without weakifying progress/fulfill/reject handlers (non-paused)
155155
///
156156
/// - e.g. Task<P, V, E> { progress, fulfill, reject, configure in ... }
157157
///
@@ -161,7 +161,7 @@ public class Task<Progress, Value, Error>: Cancellable, CustomStringConvertible
161161
}
162162

163163
///
164-
/// creates fulfilled task (non-paused)
164+
/// Create fulfilled task (non-paused)
165165
///
166166
/// - e.g. Task<P, V, E>(value: someValue)
167167
///
@@ -174,7 +174,7 @@ public class Task<Progress, Value, Error>: Cancellable, CustomStringConvertible
174174
}
175175

176176
///
177-
/// creates rejected task (non-paused)
177+
/// Create rejected task (non-paused)
178178
///
179179
/// - e.g. Task<P, V, E>(error: someError)
180180
///
@@ -187,7 +187,7 @@ public class Task<Progress, Value, Error>: Cancellable, CustomStringConvertible
187187
}
188188

189189
///
190-
/// creates promise-like task which only allows fulfill & reject (no progress & configure)
190+
/// Create promise-like task which only allows fulfill & reject (no progress & configure)
191191
///
192192
/// - e.g. Task<Any, Value, Error> { fulfill, reject in ... }
193193
///
@@ -353,15 +353,16 @@ public class Task<Progress, Value, Error>: Cancellable, CustomStringConvertible
353353
///
354354
/// - e.g. task.progress { oldProgress, newProgress in ... }
355355
///
356-
/// NOTE: `oldProgress` is always nil when `weakified = true`
356+
/// - Note: `oldProgress` is always nil when `weakified = true`
357+
/// - Returns: Self (same `Task`)
357358
///
358-
public func progress(progressClosure: ProgressTuple -> Void) -> Task
359+
public func progress(progressClosure: ProgressTuple -> Void) -> Self
359360
{
360361
var dummyCanceller: Canceller? = nil
361362
return self.progress(&dummyCanceller, progressClosure)
362363
}
363364

364-
public func progress<C: Canceller>(inout canceller: C?, _ progressClosure: ProgressTuple -> Void) -> Task
365+
public func progress<C: Canceller>(inout canceller: C?, _ progressClosure: ProgressTuple -> Void) -> Self
365366
{
366367
var token: _HandlerToken? = nil
367368
self._machine.addProgressTupleHandler(&token, progressClosure)
@@ -374,11 +375,13 @@ public class Task<Progress, Value, Error>: Cancellable, CustomStringConvertible
374375
}
375376

376377
///
377-
/// then (fulfilled & rejected) + closure returning **value**
378-
/// (a.k.a. `map` in functional programming term)
378+
/// `then` (fulfilled & rejected) + closure returning **value**.
379+
/// (similar to `map` in functional programming)
379380
///
380381
/// - e.g. task.then { value, errorInfo -> NextValueType in ... }
381382
///
383+
/// - Returns: New `Task`
384+
///
382385
public func then<Value2>(thenClosure: (Value?, ErrorInfo?) -> Value2) -> Task<Progress, Value2, Error>
383386
{
384387
var dummyCanceller: Canceller? = nil
@@ -393,11 +396,13 @@ public class Task<Progress, Value, Error>: Cancellable, CustomStringConvertible
393396
}
394397

395398
///
396-
/// then (fulfilled & rejected) + closure returning **task**
397-
/// (a.k.a. `flatMap` in functional programming term)
399+
/// `then` (fulfilled & rejected) + closure returning **task**.
400+
/// (similar to `flatMap` in functional programming)
398401
///
399402
/// - e.g. task.then { value, errorInfo -> NextTaskType in ... }
400403
///
404+
/// - Returns: New `Task`
405+
///
401406
public func then<Progress2, Value2, Error2>(thenClosure: (Value?, ErrorInfo?) -> Task<Progress2, Value2, Error2>) -> Task<Progress2, Value2, Error2>
402407
{
403408
var dummyCanceller: Canceller? = nil
@@ -410,6 +415,8 @@ public class Task<Progress, Value, Error>: Cancellable, CustomStringConvertible
410415
// - `let canceller = Canceller(); task1.then(&canceller) {...}; canceller.cancel();`
411416
// - `let task2 = task1.then {...}; task2.cancel();`
412417
//
418+
/// - Returns: New `Task`
419+
///
413420
public func then<Progress2, Value2, Error2, C: Canceller>(inout canceller: C?, _ thenClosure: (Value?, ErrorInfo?) -> Task<Progress2, Value2, Error2>) -> Task<Progress2, Value2, Error2>
414421
{
415422
return Task<Progress2, Value2, Error2> { [unowned self, weak canceller] newMachine, progress, fulfill, _reject, configure in
@@ -448,10 +455,13 @@ public class Task<Progress, Value, Error>: Cancellable, CustomStringConvertible
448455
}
449456

450457
///
451-
/// success (fulfilled) + closure returning **value**
458+
/// `success` (fulfilled) + closure returning **value**.
459+
/// (synonym for `map` in functional programming)
452460
///
453461
/// - e.g. task.success { value -> NextValueType in ... }
454462
///
463+
/// - Returns: New `Task`
464+
///
455465
public func success<Value2>(successClosure: Value -> Value2) -> Task<Progress, Value2, Error>
456466
{
457467
var dummyCanceller: Canceller? = nil
@@ -466,10 +476,13 @@ public class Task<Progress, Value, Error>: Cancellable, CustomStringConvertible
466476
}
467477

468478
///
469-
/// success (fulfilled) + closure returning **task**
479+
/// `success` (fulfilled) + closure returning **task**
480+
/// (synonym for `flatMap` in functional programming)
470481
///
471482
/// - e.g. task.success { value -> NextTaskType in ... }
472483
///
484+
/// - Returns: New `Task`
485+
///
473486
public func success<Progress2, Value2, Error2>(successClosure: Value -> Task<Progress2, Value2, Error2>) -> Task<Progress2, Value2, Error>
474487
{
475488
var dummyCanceller: Canceller? = nil
@@ -497,11 +510,14 @@ public class Task<Progress, Value, Error>: Cancellable, CustomStringConvertible
497510
}
498511

499512
///
500-
/// failure (rejected or cancelled) + closure returning **value**
513+
/// `failure` (rejected or cancelled) + closure returning **value**.
514+
/// (synonym for `mapError` in functional programming)
501515
///
502516
/// - e.g. task.failure { errorInfo -> NextValueType in ... }
503517
/// - e.g. task.failure { error, isCancelled -> NextValueType in ... }
504518
///
519+
/// - Returns: New `Task`
520+
///
505521
public func failure(failureClosure: ErrorInfo -> Value) -> Task
506522
{
507523
var dummyCanceller: Canceller? = nil
@@ -516,11 +532,14 @@ public class Task<Progress, Value, Error>: Cancellable, CustomStringConvertible
516532
}
517533

518534
///
519-
/// failure (rejected or cancelled) + closure returning **task**
535+
/// `failure` (rejected or cancelled) + closure returning **task**.
536+
/// (synonym for `flatMapError` in functional programming)
520537
///
521538
/// - e.g. task.failure { errorInfo -> NextTaskType in ... }
522539
/// - e.g. task.failure { error, isCancelled -> NextTaskType in ... }
523540
///
541+
/// - Returns: New `Task`
542+
///
524543
public func failure<Progress2, Error2>(failureClosure: ErrorInfo -> Task<Progress2, Value, Error2>) -> Task<Progress2, Value, Error2>
525544
{
526545
var dummyCanceller: Canceller? = nil
@@ -546,11 +565,41 @@ public class Task<Progress, Value, Error>: Cancellable, CustomStringConvertible
546565
}.name("\(self.name)-failure")
547566
}
548567

568+
///
569+
/// Add side-effects after completion.
570+
///
571+
/// - Note: This method doesn't create new task, so it has better performance over `then()`/`success()`/`failure()`.
572+
/// - Returns: Self (same `Task`)
573+
///
574+
public func on(success success: (Value -> Void)? = nil, failure: (ErrorInfo -> Void)? = nil) -> Self
575+
{
576+
var dummyCanceller: Canceller? = nil
577+
return self.on(&dummyCanceller, success: success, failure: failure)
578+
}
579+
580+
public func on<C: Canceller>(inout canceller: C?, success: (Value -> Void)? = nil, failure: (ErrorInfo -> Void)? = nil) -> Self
581+
{
582+
let selfMachine = self._machine
583+
584+
self._then(&canceller) {
585+
if let value = selfMachine.value.rawValue {
586+
success?(value)
587+
}
588+
else if let errorInfo = selfMachine.errorInfo.rawValue {
589+
failure?(errorInfo)
590+
}
591+
}
592+
593+
return self
594+
}
595+
596+
/// Pause task.
549597
public func pause() -> Bool
550598
{
551599
return self._machine.handlePause()
552600
}
553601

602+
/// Resume task.
554603
public func resume() -> Bool
555604
{
556605
return self._machine.handleResume()
@@ -562,11 +611,13 @@ public class Task<Progress, Value, Error>: Cancellable, CustomStringConvertible
562611
// - `public func cancel(error: Error? = nil) -> Bool`
563612
// - `public func cancel(_ error: Error? = nil) -> Bool` (segfault in Swift 1.2)
564613
//
614+
/// Cancel task.
565615
public func cancel() -> Bool
566616
{
567617
return self.cancel(error: nil)
568618
}
569619

620+
/// Cancel task.
570621
public func cancel(error error: Error?) -> Bool
571622
{
572623
return self._cancel(error)

‎SwiftTaskTests/SwiftTaskTests.swift

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,57 @@ class SwiftTaskTests: _TestCase
422422
self.wait()
423423
}
424424

425+
//--------------------------------------------------
426+
// MARK: - On
427+
//--------------------------------------------------
428+
429+
func testOn_success()
430+
{
431+
let expect = self.expectationWithDescription(__FUNCTION__)
432+
433+
Task<(), String, ErrorString> { progress, fulfill, reject, configure in
434+
435+
self.perform {
436+
fulfill("OK")
437+
}
438+
439+
}.on(success: { value in
440+
441+
XCTAssertEqual(value, "OK")
442+
expect.fulfill()
443+
444+
}).on(failure: { error, isCancelled in
445+
XCTFail("Should never reach here.")
446+
})
447+
448+
self.wait()
449+
}
450+
451+
func testOn_failure()
452+
{
453+
let expect = self.expectationWithDescription(__FUNCTION__)
454+
455+
Task<(), String, ErrorString> { progress, fulfill, reject, configure in
456+
457+
self.perform {
458+
reject("NG")
459+
}
460+
461+
}.on(success: { value in
462+
463+
XCTFail("Should never reach here.")
464+
465+
}).on(failure: { error, isCancelled in
466+
467+
XCTAssertEqual(error!, "NG")
468+
XCTAssertFalse(isCancelled)
469+
expect.fulfill()
470+
471+
})
472+
473+
self.wait()
474+
}
475+
425476
//--------------------------------------------------
426477
// MARK: - Progress
427478
//--------------------------------------------------

‎circle.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
machine:
22
xcode:
3-
version: "7.0"
3+
version: "7.1"
44

55
checkout:
66
post:

0 commit comments

Comments
 (0)
Please sign in to comment.