[iOS] [OC] custom Promise handles serial asynchronous operations

background

Many operations in iOS applications are asynchronous, such as:

  • Callback for network requests
  • UIAlertController waits for the user to click the callback of the event
  • Positioned callbacks

So, when the need to perform these operations by serial, due to different conditions and different operation callback results callback order, if the continuous nesting leads to serious business coupling, multiple operations and possible error handling callback will form often say “callback hell” (for example, as the following pseudo code). Logic caused by poor readability, maintain and affect the future.

Hell - (void) / / / callback callbackHell {[TestManager doSomethingWithCompletion:^{(@ NSLog "No 1 done"); [TestManager doSomethingWithCompletion:^{(@ NSLog "No 2 done"); [TestManager doSomethingWithCompletion:^{(@ NSLog "No 3 done");}];}];}];}

For asynchronous callback processing in serial situations, the asynchronous callback can be encapsulated once, and this expectation of performing an operation is usually called Promise.

After each asynchronous callback is encapsulated, it is put into the PromiseManager process, and the effect is illustrated below:

Just use the Promise - (void) testPromise *a promiseWithHandler:^ {GSPromise = [GSPromise (dispatch_block_t then) {[TestManager doSomethingWithCompletion:^{(@ NSLog "done a"); (then);}];}]; GSPromise *b = [GSPromise promiseWithHandler:^ (dispatch_block_t then) {[TestManager doSomethingWithCompletion:^{(@ NSLog "done B"); then (}]);}];; GSPromise *c = [GSPromise promiseWithHandler:^ (dispatch_block_t then) {[TestManager doSomethingWithCompletion:^{(@ NSLog "done C"); (then);}];}]; GSPromiseManager *manager = [GSPromiseManager manangerWithPromises:@[a b]]; [manager addPromise:c];}

Solution

Serial operation order is executed, the next operation after the end of an operation, it can be executed the next operation of the event, encapsulated in a block (called then), and a operation is performed after the completion of the call.

In addition, the method of operation is required to execute the package into a block (called handler), each operation has a handler property, the property declaration for the GSPromisable protocol (see below), to follow the requirements of the operation.

What a promise will execute / * * @param then should call this block after promise done / typedef void (^GSPromiseHandler) (dispatch_block_t then); @protocol GSPromisable < NSObject> the handler which a promise; / * * * should retain @ property (nonatomic, copy) GSPromiseHandler handler; @end

Among them, follow the GSPromisable protocol or promise container array are added to the PromiseManager management, the handler property of each promise by external PromiseManager at the right time to call. For the realization of PromiseManager on serial manager in executive management, operation of the handler when the above then operation passed to handler, so handler in the complete call then itself after the operation, to achieve the next operation, to achieve the following:

Try to handle next / / / operation - (void) try2Start (self.isWorking) {if return; ID < GSPromisable> first = container.firstObject; if (first!) return; self.working = YES; dispatch_block_t = then self.working = NO ^{; @ synchronized (self) {if (container.firstObject!) return [container; removeObjectAtIndex:0] [self;} try2Start] first.handler (then);};};

It is worth mentioning that this design thinking similar to the previous “[iOS] [OC]” on the block callback, higher order function, callback, re call and project practice

Source code and demo

[email protected]

extend

With regard to asynchronous handling, there are many excellent open source frameworks that you can learn and recommend:

  • PromiseKit
  • RxSwift

Thanks to colleagues, Zoe, his relentless pursuit of work has led to better solutions and improvements.