Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I would like to propose another approach which uses a helper library which makes asynchronous tasks much easier to implement: it uses "Promises" as a means to signal the completion (or failure) of an asynchronous tasks.</p> <p>Basically, instead of a completion block, an asynchronous tasks (method in this case) looks as follows:</p> <pre><code>- (RXPromise*) doSomethingAsync; </code></pre> <p>The <em>eventual result</em> respectively a failure can be obtained via handlers which will be "registered" like shown below:</p> <pre><code>- (void) foo { RXPromise* promise = [self doSomethingAsync]; promise.then( &lt;completion handler block&gt;, &lt;error handler block&gt; ); } </code></pre> <p>or shorter, and with the handler placeholders filled with actual code:</p> <pre><code>- (void) foo { [self doSomethingAsync] .then(^id(id result) { // result is the eventual result of the asynchronous task return nil; // return the result of the handler }, id(NSError*error) { NSLog(@"ERROR: %@, error"); // the task failed with error return nil; }); } </code></pre> <p>Note: the handlers itself execute on a private thread (actual a concurrent dispatch queue). In order to synchronize shared access within handlers one can explicitly specify the dispatch queue where the handler will be executed:</p> <pre><code>- (void) foo { [self doSomethingAsync] .thenOn(dispatch_get_main_queue()), ^id(id result) { // Here, we are executing on the main thread // result is the eventual result of the asynchronous task return nil; // return the result of the handler }, id(NSError*error) { // Here, we are executing on the main thread NSLog(@"ERROR: %@, error"); // the task failed with error return nil; }); } </code></pre> <p>Note that the asynchronous tasks executed in <code>[self doSomethingAsync]</code> may be executed on its own private thread (or queue).</p> <p>"Continuation" of more than one asynchronous tasks can be easily accomplished:</p> <pre><code>task1() .then(^id(id result1{ return task2(result1); }, nil) .then(^id(id result2) { return task3(result2); }, nil) .then(nil, ^id(NSError*error) NSLog(@"Something went wrong in task1 or task2 or task3: %@", error); return nil; ); </code></pre> <p>After this short introduction you can solve your problem as follows:</p> Define your asynchronous tasks, which return a RXPromise: <pre><code>- (RXPromise*) prepareWorkEntry1FromManagedObjectContext:(NSManagedObjectContext *)context; - (RXPromise*) prepareWorkEntry2FromManagedObjectContext:(NSManagedObjectContext *)context; - (RXPromise*) prepareWorkEntry3FromManagedObjectContext:(NSManagedObjectContext *)context; - (RXPromise*) prepareWorkEntry1FromManagedObjectContext:(NSManagedObjectContext *)context { RXPromise* promise = [RXPromise new]; [context performBlock:^{ Object *object = nil; createObject(object); if (object) { // success [promise fulfillWithValue:object]; } else { // failure [promise rejectWithReason:@"object creation failed"]; } }]; return promise; } </code></pre> <p>Likewise, implement the other tasks.</p> Combine the results in the handlers: <pre><code>- (void) foo { [self prepareWorkEntry1FromManagedObjectContext:moc] .thenOn(self.sync_queue, (^id(id object)) { [self.dataSourceArray addObject:object]; return @"Finished 1"; }, nil); [self prepareWorkEntry2FromManagedObjectContext:moc] .thenOn(self.sync_queue, (^id(id object)) { [self.dataSourceArray addObject:object]; return @"Finished 2"; }, nil); [self prepareWorkEntry3FromManagedObjectContext:moc] .thenOn(self.sync_queue, (^id(id object)) { [self.dataSourceArray addObject:object]; return @"Finished 3"; }, nil); } </code></pre> <p>Note that the <code>dataSourceArray</code> will be accessed in the dedicated <code>sync_queue</code>. This shall be a serial dispatch queue.</p> <p>Note also, that method foo is effectively asynchronous.</p> <p>There is also the possibility to "asynchronously wait" until a number of asynchronous tasks have been completed:</p> <pre><code>- (void) foo { NSArray* promises = @[ [self prepareWorkEntry1FromManagedObjectContext:moc] .thenOn(self.sync_queue, (^id(id object)) { [self.dataSourceArray addObject:object]; return @"Finished 1"; }, nil), [self prepareWorkEntry2FromManagedObjectContext:moc] .thenOn(self.sync_queue, (^id(id object)) { [self.dataSourceArray addObject:object]; return @"Finished 2"; }, nil), [self prepareWorkEntry3FromManagedObjectContext:moc] .thenOn(self.sync_queue, (^id(id object)) { [self.dataSourceArray addObject:object]; return @"Finished 3"; }, nil) ]; [RXPromise all:promises] .then(^id(id arrayOfPromises){ // all tasks *and its handlers* finished. ... return nil; }, nil); } </code></pre> <p>I'm the author of this library which you can find here: <a href="https://github.com/couchdeveloper/RXPromise" rel="nofollow">RXPromise</a>. </p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload