Send a bunch of requests one-by-one [closed]

偶尔善良 提交于 2019-12-23 06:00:12

问题


I need to send 100 network requests to my server one-by-one and get notified when the 100th is done.

I'm using AFNetworking and was thinking about a solution of this problem. Can anyone recommend me something?


回答1:


A couple of thoughts:

  1. If really just going to run each request serially (i.e. one after another), you could do:

    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    queue.maxConcurrentOperationCount = 1;
    
    NSOperation *completionOperation = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"All operations done");
    }];
    
    for (NSInteger i = 0; i < operationCount; i++) {
        AFHTTPRequestOperation *operation = ... // create your operation here
    
        [completionOperation addDependency:operation];
    
        [queue addOperation:operation];
    }
    
    [queue addOperation:completionOperation];
    

    Note, using operation queue like this offers the advantage that you can easily cancel all the operations in that queue should you ever need to.

    If the order that these are performed is critical, you might want to establish explicit dependencies between the operations, e.g.:

    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    queue.maxConcurrentOperationCount = 1;
    
    NSOperation *completionOperation = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"All operations done");
    }];
    
    NSOperation *priorOperation = nil;
    
    for (NSInteger i = 0; i < operationCount; i++) {
        AFHTTPRequestOperation *operation = ... // create your operation here
    
        [completionOperation addDependency:operation];
    
        if (priorOperation) [operation addDependency:priorOperation];
    
        [queue addOperation:operation];
    
        priorOperation = operation;
    }
    
    [queue addOperation:completionOperation];
    
  2. The question for me is whether you absolutely only want to run one at a time. You pay a significant performance penalty for that. Generally you'd use that first code sample (where the only explicit dependencies are to the completion operation) and set maxConcurrentOperationCount to something like 4, enjoying concurrency and its consequent significant performance gain (while at the same time, constraining the degree of concurrency to some reasonable number that won't use up all of your worker threads, risk having requests time out, etc.).

  3. You haven't said what these 100 operations are, but if it's a bunch of downloads, you might want to consider a "lazy loading" pattern, loading the data asynchronously as you need it, rather than all at once.

    If downloading images, for example, you might achieve this using the AFNetworking UIImageView category.




回答2:


This is a specific form of a common question, which is "how do I call a sequence of block operations and get notified when the last one finishes?"

One idea is to make a "to-do list" using the parameters for each request. Say each request takes a number 0..99. Now pseudo-code would looks like this:

@property(nonatomic, copy) void (^done)(BOOL);      // we'll need to save a completion block
@property(nonatomic, strong) NSMutableArray *todo;  // might as well save this too

- (void)makeRequestsThenInvoke:(void (^)(BOOL))done {

    self.todo = [NSMutableArray arrayWithArray:@[@99, @98, @97 ... @0]];
    // make this in a loop using real params to your network request (whatever distinguishes each request)

    self.done = done;
    [self makeRequests];
}


- (void)makeRequests {

    if (!self.todo.count) {    // nothing todo?  then we're done
        self.done(YES);
        self.done = nil;       // avoid caller-side retain cycle
        return;
    }
    // otherwise, get the next item todo
    NSNumber *param = [self.todo lastObject];
    // build a url with param, e.g. http://myservice.com/request?param=%@ <- param goes there

    [afManager post:url success:success:^(AFHTTPRequestOperation *operation, id responseObject) {

        // handle the result

        // now update the todo list
        [self.todo removeLastObject];
         // call ourself to do more, but use performSelector so we don't wind up the stack
        [self performSelector:@selector(makeRequests) withObject:nil afterDelay:0.0];
    }];
}


来源:https://stackoverflow.com/questions/20474422/send-a-bunch-of-requests-one-by-one

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!