Objective-C块更好的asynchronous控制stream程

我正在使用AFNetworking对Web服务进行asynchronous调用。 这些呼叫中的一些必须被链接在一起,其中呼叫A的结果由呼叫C使用的呼叫B使用,等等

AFNetworking会在创build操作时处理设置了成功/失败块的asynchronous调用结果:

NSURL *url = [NSURL URLWithString:@"http://api.twitter.com/1/statuses/public_timeline.json"]; NSURLRequest *request = [NSURLRequest requestWithURL:url]; AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) { NSLog(@"Public Timeline: %@", JSON); } failure:nil]; [operation start]; 

这会导致嵌套的asynchronous调用块迅速变得不可读。 当任务不相互依赖,而是必须并行执行,执行取决于所有操作的结果时,情况会更加复杂。

似乎更好的方法是利用承诺框架来清理控制stream程。

我遇到了MAFuture,但无法弄清楚如何最好地将其与AFNetworking相结合。 由于asynchronous调用可能有多个结果(成功/失败),并没有返回值,它似乎不是一个理想的契合。

任何指针或想法,将不胜感激。

我还没有使用它,但它听起来像反应cocoa被devise来做你刚才描述的。

我为此创build了一个轻量级的解决scheme。 这就是所谓的音序器,它在github上 。

它使链接API调用(或任何其他asynchronous代码)容易和简单。

下面是使用AFNetworking的一个例子:

 Sequencer *sequencer = [[Sequencer alloc] init]; [sequencer enqueueStep:^(id result, SequencerCompletion completion) { NSURL *url = [NSURL URLWithString:@"https://alpha-api.app.net/stream/0/posts/stream/global"]; NSURLRequest *request = [NSURLRequest requestWithURL:url]; AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) { completion(JSON); } failure:nil]; [operation start]; }]; [sequencer enqueueStep:^(NSDictionary *feed, SequencerCompletion completion) { NSArray *data = [feed objectForKey:@"data"]; NSDictionary *lastFeedItem = [data lastObject]; NSString *cononicalURL = [lastFeedItem objectForKey:@"canonical_url"]; NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:cononicalURL]]; AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request]; [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { completion(responseObject); } failure:nil]; [operation start]; }]; [sequencer enqueueStep:^(NSData *htmlData, SequencerCompletion completion) { NSString *html = [[NSString alloc] initWithData:htmlData encoding:NSUTF8StringEncoding]; NSLog(@"HTML Page: %@", html); completion(nil); }]; [sequencer run]; 

在Gowalla使用AFNetworking成功地将呼叫链接在一起并不罕见。

我的build议是尽可能地将networking请求和序列化分解为模型中的类方法。 然后,对于需要创build子请求的请求,可以在成功块中调用这些方法。

此外,如果您还没有使用它, AFHTTPClient大大简化了这些复杂的networking交互。

PromiseKit可能是有用的。 它似乎是更受欢迎的承诺实现之一,而其他人已经写了类别来将它与像AFNetworking这样的库集成,参见PromiseKit-AFNetworking 。

在Github上有一个Objective-C实现CommonJS风格的promise:

https://github.com/mproberts/objc-promise

示例(取自Readme.md)

 Deferred *russell = [Deferred deferred]; Promise *promise = [russell promise]; [promise then:^(NSString *hairType){ NSLog(@"The present King of France is %@!", hairType); }]; [russell resolve:@"bald"]; // The present King of France is bald! 

我还没有尝试过这个图书馆,但看起来很有希望,尽pipe这个例子有些不尽如人意。 (对不起,我无法抗拒)。