Skip to content

Commit

Permalink
Merge pull request #674 from igor-makarov/master
Browse files Browse the repository at this point in the history
expand the ObjC AnyPromise interface for catching
  • Loading branch information
mxcl committed Jun 8, 2017
2 parents c298b43 + db8d5df commit 85238e3
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 5 deletions.
2 changes: 1 addition & 1 deletion Sources/AnyPromise+Private.h
Expand Up @@ -27,7 +27,7 @@

@interface AnyPromise (Swift)
- (AnyPromise * __nonnull)__thenOn:(__nonnull dispatch_queue_t)q execute:(id __nullable (^ __nonnull)(id __nullable))body;
- (AnyPromise * __nonnull)__catchWithPolicy:(PMKCatchPolicy)policy execute:(id __nullable (^ __nonnull)(id __nullable))body;
- (AnyPromise * __nonnull)__catchOn:(__nonnull dispatch_queue_t)q withPolicy:(PMKCatchPolicy)policy execute:(id __nullable (^ __nonnull)(id __nullable))body;
- (AnyPromise * __nonnull)__alwaysOn:(__nonnull dispatch_queue_t)q execute:(void (^ __nonnull)(void))body;
- (void)__pipe:(void(^ __nonnull)(__nullable id))body;
- (AnyPromise * __nonnull)initWithResolverBlock:(void (^ __nonnull)(PMKResolver __nonnull))resolver;
Expand Down
40 changes: 40 additions & 0 deletions Sources/AnyPromise.h
Expand Up @@ -100,6 +100,35 @@ typedef NS_ENUM(NSInteger, PMKCatchPolicy) {
- (AnyPromise * __nonnull(^ __nonnull)(id __nonnull))catch NS_REFINED_FOR_SWIFT;
#endif

/**
The provided block is executed when the receiver is rejected.
Provide a block of form `^(NSError *){}` or simply `^{}`. The parameter has type `id` to give you the freedom to choose either.
The provided block always runs on the global background queue.
@warning *Note* Cancellation errors are not caught.
@warning *Note* Since catch is a c++ keyword, this method is not available in Objective-C++ files. Instead use catchWithPolicy.
@see catchWithPolicy
*/
- (AnyPromise * __nonnull(^ __nonnull)(id __nonnull))catchInBackground NS_REFINED_FOR_SWIFT;


/**
The provided block is executed when the receiver is rejected.
Provide a block of form `^(NSError *){}` or simply `^{}`. The parameter has type `id` to give you the freedom to choose either.
The provided block always runs on queue provided.
@warning *Note* Cancellation errors are not caught.
@see catchWithPolicy
*/
- (AnyPromise * __nonnull(^ __nonnull)(dispatch_queue_t __nonnull, id __nonnull))catchOn NS_REFINED_FOR_SWIFT;

/**
The provided block is executed when the receiver is rejected with the specified policy.
Expand All @@ -109,6 +138,17 @@ typedef NS_ENUM(NSInteger, PMKCatchPolicy) {
*/
- (AnyPromise * __nonnull(^ __nonnull)(PMKCatchPolicy, id __nonnull))catchWithPolicy NS_REFINED_FOR_SWIFT;

/**
The provided block is executed when the receiver is rejected with the specified policy.
Specify the policy with which to catch as the first parameter to your block. Either for all errors, or all errors *except* cancellation errors.
The provided block always runs on queue provided.
@see catch
*/
- (AnyPromise * __nonnull(^ __nonnull)(dispatch_queue_t __nonnull, PMKCatchPolicy, id __nonnull))catchOnWithPolicy NS_REFINED_FOR_SWIFT;

/**
The provided block is executed when the receiver is resolved.
Expand Down
28 changes: 26 additions & 2 deletions Sources/AnyPromise.m
Expand Up @@ -38,17 +38,41 @@ - (instancetype)initWithResolver:(PMKResolver __strong *)resolver {
};
}

- (AnyPromise *(^)(dispatch_queue_t, id))catchOn {
return ^(dispatch_queue_t q, id block) {
return [self __catchOn:q withPolicy:PMKCatchPolicyAllErrorsExceptCancellation execute:^(id obj) {
return PMKCallVariadicBlock(block, obj);
}];
};
}

- (AnyPromise *(^)(id))catch {
return ^(id block) {
return [self __catchWithPolicy:PMKCatchPolicyAllErrorsExceptCancellation execute:^(id obj) {
return [self __catchOn:PMKDefaultDispatchQueue() withPolicy:PMKCatchPolicyAllErrorsExceptCancellation execute:^(id obj) {
return PMKCallVariadicBlock(block, obj);
}];
};
}

- (AnyPromise *(^)(id))catchInBackground {
return ^(id block) {
return [self __catchOn:dispatch_get_global_queue(0, 0) withPolicy:PMKCatchPolicyAllErrorsExceptCancellation execute:^(id obj) {
return PMKCallVariadicBlock(block, obj);
}];
};
}

- (AnyPromise *(^)(dispatch_queue_t, PMKCatchPolicy, id))catchOnWithPolicy {
return ^(dispatch_queue_t q, PMKCatchPolicy policy, id block) {
return [self __catchOn:q withPolicy:policy execute:^(id obj) {
return PMKCallVariadicBlock(block, obj);
}];
};
}

- (AnyPromise *(^)(PMKCatchPolicy, id))catchWithPolicy {
return ^(PMKCatchPolicy policy, id block) {
return [self __catchWithPolicy:policy execute:^(id obj) {
return [self __catchOn:PMKDefaultDispatchQueue() withPolicy:policy execute:^(id obj) {
return PMKCallVariadicBlock(block, obj);
}];
};
Expand Down
4 changes: 2 additions & 2 deletions Sources/AnyPromise.swift
Expand Up @@ -206,9 +206,9 @@ import Foundation
})
}

@objc func __catchWithPolicy(_ policy: CatchPolicy, execute body: @escaping (Any?) -> Any?) -> AnyPromise {
@objc func __catchOn(_ q: DispatchQueue, withPolicy policy: CatchPolicy, execute body: @escaping (Any?) -> Any?) -> AnyPromise {
return AnyPromise(sealant: { resolve in
state.catch(on: .default, policy: policy, else: resolve) { err in
state.catch(on: q, policy: policy, else: resolve) { err in
makeHandler(body, resolve)(err as NSError)
}
})
Expand Down
35 changes: 35 additions & 0 deletions Tests/CorePromise/01_AnyPromiseTests.m
Expand Up @@ -713,6 +713,41 @@ - (void)test_58_just_finally {
[self waitForExpectationsWithTimeout:1 handler:nil];
}

- (void)test_59_catch_in_background {
id ex1 = [self expectationWithDescription:@""];

[AnyPromise promiseWithResolverBlock:^(PMKResolver resolve) {
id err = [NSError errorWithDomain:@"a" code:123 userInfo:nil];
resolve(err);
}].catchInBackground(^(NSError *err){
XCTAssertEqual(err.code, 123);
XCTAssertFalse([NSThread isMainThread]);
[ex1 fulfill];
});

[self waitForExpectationsWithTimeout:1 handler:nil];
}

- (void)test_60_catch_on_specific_queue {
id ex1 = [self expectationWithDescription:@""];

NSString *expectedQueueName = @"specific queue 123";
dispatch_queue_t q = dispatch_queue_create(expectedQueueName.UTF8String, DISPATCH_QUEUE_SERIAL);

[AnyPromise promiseWithResolverBlock:^(PMKResolver resolve) {
id err = [NSError errorWithDomain:@"a" code:123 userInfo:nil];
resolve(err);
}].catchOn(q, ^(NSError *err){
XCTAssertEqual(err.code, 123);
XCTAssertFalse([NSThread isMainThread]);
NSString *currentQueueName = [NSString stringWithFormat:@"%s", dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL)];
XCTAssertEqualObjects(expectedQueueName, currentQueueName);
[ex1 fulfill];
});

[self waitForExpectationsWithTimeout:1 handler:nil];
}

- (void)test_properties {
Injected.errorUnhandler = ^(NSError *err){
XCTAssertEqualObjects(err.localizedDescription, @"2");
Expand Down

0 comments on commit 85238e3

Please sign in to comment.