Chaining asynchronous operations from an array of objects with ReactiveCocoa

前端 未结 1 677
小蘑菇
小蘑菇 2021-02-02 02:26

I have an array of entities and I want to perform asynchronous operations on the entities. The operations should be chained and run in the same order with the entities in the ar

相关标签:
1条回答
  • 2021-02-02 03:28

    First, you'll need a wrapper method that performs your async operation, which will return a signal. Let's assume the async operation operation takes a completion block. From the sounds of it, you don't care about the values, you want the side effects, in which case the signal does not send values, it only completes.

    - (RACSignal *)asyncOperation {
        return [RACSignal createSignal:^RACDisposable * (id<RACSubscriber> subscriber) {
            [self asyncOperationWithCompletion:^{
                [subscriber sendCompleted];
            }];
            return nil; // `nil` means there's no way to cancel.
        }];
    }
    

    EDIT: Thanks to the comment by Justin Spahr-Summers, here is a much simpler approach to chaining the operations:

    RACSignal *signal = [RACSignal concat:[array.rac_sequence map:^(id entity) {
        return [entity asyncOperation];
    }]];
    

    ReactiveCocoa's +concat: operator takes a collection of signals and subscribes to the signals one at a time, waiting for completion of one signal before subscribing to its successor. Using -rac_sequence here is for the purpose of mapping the entities to the operation signals.

    In this context, the use of +concat: achieves the same effect as the -then: chaining from my initial answer below.


    With the RAC wrapper, a solution is to start with an empty signal, and build a chain by iterating over the entities and assembling the operations using -then:. The -then: operation essentially waits for the previous operation to complete before beginning the next.

    RACSignal *signal = [RACSignal empty];
    for (id entity in array) {
        signal = [signal then:^{
            return [entity asyncOperation];
        }];
    }
    
    [signal subscribeCompleted:^{
        // At this point, all operations have completed
    }];
    

    At this point what you have is:

    [[[[RACSignal empty]
        then:^{ return [entity1 asyncOperation]; }]
        then:^{ return [entity2 asyncOperation]; }]
        // ...
        then:^{ return [entityN asyncOperation]; }]
    

    ReactiveCocoa has helpful documentation and very well documented headers, both of which were very valuable to me when I was new.

    0 讨论(0)
提交回复
热议问题