【问题标题】:AFNetworking cancelAllOperations prevents batch completionBlock from firingAFNetworking cancelAllOperations 防止批量完成块触发
【发布时间】:2013-07-22 00:10:37
【问题描述】:

我正在使用enqueueBatchOfHTTPRequestOperations 提交一批请求。如果任何请求失败,我想立即取消任何其他仍在进行的请求。为此,我将单个操作的失败回调设置为执行[client.operationQueue cancelAllOperations];

这似乎取消了所有剩余的操作,但它也阻止了批处理的整体完成块执行...这是我试图测试此行为的代码(其中一个请求始终设置为在服务器)。

AFHTTPClient *client = [AFHTTPClient clientWithBaseURL:[NSURL URLWithString:@"http://arahlf.com"]];

NSMutableArray *requests = [[NSMutableArray alloc] init];

for (int i = 0; i < 10; i++) {
    NSURLRequest *request = [client requestWithMethod:@"GET" path:@"echo.php" parameters:@{ @"sleep": @(i) }];
    AFHTTPRequestOperation *operation = [client HTTPRequestOperationWithRequest:request success:nil failure:nil];
    [operation setCompletionBlockWithSuccess:nil failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        NSLog(@"Request failed, cancelling all operations.");
        [client.operationQueue cancelAllOperations];
    }];

    [requests addObject:operation];
}

[client enqueueBatchOfHTTPRequestOperations:requests progressBlock:^(NSUInteger numberOfFinishedOperations, NSUInteger totalNumberOfOperations) {
    NSLog(@"Progress: %i/%i", numberOfFinishedOperations, totalNumberOfOperations);

} completionBlock:^(NSArray *operations) {
    NSLog(@"All done!");
}];

对我来说,completionBlock 永远不会被执行。此外,由于一个失败的请求取消了剩余的请求(这也触发了失败块),cancelAllOperations 实际上被执行了很多次。

有没有更好的方法来达到这个效果?

【问题讨论】:

  • 我可以清楚地了解您所面临的问题,但我无法理解您想要达到的目标到底是什么?对您的实际用例进行高级描述将非常有帮助。 (即你有一批请求,当它失败/成功时你希望发生什么?)
  • 我正在执行某种“数据同步”,其中大约有 10 个请求来获取各种数据。有些请求需要很长时间才能完成。如果任何请求失败,则同步本身已失败,并且没有理由等待其余请求完成(可能仍然需要一段时间),因此我想取消任何仍在运行的请求。这有意义吗?
  • 是的,确实如此。现在,您成功地取消了您的请求,而不是等待。那部分正在工作。但是当您取消它们时,您的部分代码永远不会被调用(完成块),而部分代码会被多次调用(失败块)。这些块中究竟是什么导致上述副作用导致问题?
  • 什么都没有 :) 在我重构我的应用程序以利用 AFNetworking + NSOperation/NSOperationQueue 发出同步请求之前,我正在尝试创建它作为概念证明。我在我的问题中发布的代码完全重现了这个问题。批处理请求的整体完成块永远不会运行。
  • 哦,我的错。因此,即使批处理请求成功,也不会触发完成块。这显然是一个值得提交到他们的 GitHub 存储库的问题。希望你在那里提交它会得到一些运气。

标签: objective-c afnetworking nsoperation nsoperationqueue


【解决方案1】:

当您执行operationQueue cancelAllOperations 时,除了所有其他操作之外,您实际上是在取消在批处理完成时触发的相关操作。

也就是说,在你的例子中,取消了11个操作:10个网络操作+依赖的批处理完成操作。

setCompletionblock:... 中的以下更改允许按预期触发批处理完成:

[[client.operationQueue.operations filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
  return [evaluatedObject isKindOfClass:[AFHTTPRequestOperation class]];
}]] makeObjectsPerformSelector:@selector(cancel)];

【讨论】:

  • 谢谢。我认为这可能与此有关,但我不确定取消依赖操作是否仍会触发该操作。在旁注中,取消请求时,我是否需要担心锁定/同步?似乎所有回调都在主线程上运行,但我有点不确定......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-12-17
  • 1970-01-01
  • 2012-06-18
  • 1970-01-01
  • 2011-09-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多