使用 AFNetworking 的 enqueueBatchOfHTTPRequestOperations 失败时如何重新添加操作
Posted
技术标签:
【中文标题】使用 AFNetworking 的 enqueueBatchOfHTTPRequestOperations 失败时如何重新添加操作【英文标题】:How to re-add operations when they fail using enqueueBatchOfHTTPRequestOperations from AFNetworking 【发布时间】:2013-01-07 23:06:53 【问题描述】:我有一种方法可以使用 AFNetworking 调用 enqueueBatchOfHTTPRequestOperations 将文件列表从 Web 服务器下载到 iPad。每隔一段时间我就会遇到一次失败的操作(通常是当文件较大时)。从历史上看,我单独下载每个文件,然后简单地再次调用该操作,直到达到一定的重试次数。
我已重构代码以使用 enqueueBatchOfHTTPRequestOperations。这很好用,但我不知道如何获取有关“特定”操作失败的通知,并且我不知道如果它们失败了如何将它们重新添加到队列中。
这是我用来下载“n”个文件的代码:
NSMutableArray *operationsArray = [[NSMutableArray alloc]init];
for (MINPageDefinition *currPage in [[MINPageStore sharedInstance] pageArray])
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *serverLibraryURL = [defaults objectForKey:kRootURL];
serverLibraryURL = [serverLibraryURL stringByAppendingPathComponent:kPageDefinitionsDirectory];
serverLibraryURL = [serverLibraryURL stringByAppendingPathComponent:currPage.pageImageName];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:serverLibraryURL]];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
operation.outputStream = [NSOutputStream outputStreamToFileAtPath:currPage.pageImageURL append:NO];
[operationsArray addObject:operation];
if ([operationsArray count] > 0)
AFHTTPClient *client = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:@""]];
void (^progressBlock)(NSUInteger numberOfCompletedOperations, NSUInteger totalNumberOfOperations) = ^(NSUInteger numberOfCompletedOperations, NSUInteger totalNumberOfOperations)
NSLog(@"%d proccesses completed out of %d", numberOfCompletedOperations, totalNumberOfOperations);
;
void (^completionBlock)(NSArray *operations) = ^(NSArray *operations)
NSLog(@"All operations completed");
;
[client enqueueBatchOfHTTPRequestOperations:operationsArray
progressBlock:progressBlock
completionBlock:completionBlock];
以前,我有一个执行操作的方法。失败时,失败块将递归调用自身。如果操作失败,如何修改此代码以重试最多“n”次?
【问题讨论】:
非常接近...***.com/questions/12220986/… 你也可以查看github.com/AFNetworking/AFNetworking/issues/596 实际上,在我最初的实现中,这正是我正在做的。如果某个操作失败,我会递归调用封装该操作的方法。我现在遇到的问题是因为我已经将实现更改为使用 enqueueBatchOfHTTPRequestOperations 进行排队操作。此方法迭代“n”个操作。我知道我可以遍历处理程序中的操作。但是我如何重新添加然后重新排队这些操作? 【参考方案1】:检查下面的代码@justLearningAgain
[[WfServices sharedClient] GET:kGetAddress parameters:dicParam success:^(AFHTTPRequestOperation *operation, id responseObject)
NSLog(@"RESPONSE ::: %@",responseObject);
failure:^(AFHTTPRequestOperation *operation, NSError *error)
];
+ (WfServices *)sharedClient
static WfServices * _sharedClient = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^
_sharedClient = [[WfServices alloc] initWithBaseURL:[NSURL URLWithString:kWFBaseURLString]];
);
return _sharedClient;
【讨论】:
【参考方案2】:您不能像这样将单个失败的操作再次排入该操作的失败块中吗?
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject)
failure:^(AFHTTPRequestOperation *operation, NSError *error)
[[APIClient sharedClient] enqueueHTTPRequestOperation:operation];
];
其中[APIClient sharedClient]
是对您的AFHTTPClient
子类的引用(单例与否)。
【讨论】:
否,因为您无法将已完成的操作添加到操作队列中。如果你尝试,它会抛出一个NSInvalidArgumentException
。即使请求在网络级别失败,操作本身也完成了。【参考方案3】:
我认为AFNetworking Auto-Retry 可能会有所帮助。
或者您可以在您的 AFHTTPClient 中覆盖以下方法。
考虑 resumeTasksArray = 您需要重新添加到队列中的操作数组。
NSMutableArray *resumeTasksArray; before @implementation AFHTTPClient
- (AFHTTPRequestOperation *)HTTPRequestOperationWithRequest:(NSURLRequest *)request
success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
void(^authFailBlock)(AFHTTPRequestOperation *opr, NSError *err) = ^(AFHTTPRequestOperation *opr, NSError *err)
[resumeTasksArray addObject:request];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^
//now, queue up and execute the original task
for (NSURLRequest *previousRequest in resumeTasksArray)
NSLog(@"^^^^^^^^^^^^^^^^^^^^^^^^^^^^Resume Task URL - %@", previousRequest.URL);
NSMutableURLRequest *newRequest = [previousRequest mutableCopy];
[newRequest setValue:[NSString stringWithFormat:@"Bearer %@", AppSingleton.access_token] forHTTPHeaderField:@"Authorization"];
AFHTTPRequestOperation *opera10n = [[AFHTTPRequestOperation alloc]initWithRequest:newRequest];
opera10n.responseSerializer = self.responseSerializer;
[opera10n setCompletionBlockWithSuccess:success failure:failure];
if (![[self.operationQueue operations] containsObject:opera10n])
[[self operationQueue] addOperation:opera10n];
[opera10n start];
[resumeTasksArray removeAllObjects];
);
;
AFHTTPRequestOperation *operation = [super HTTPRequestOperationWithRequest:request success:success failure:authFailBlock];
return operation;
【讨论】:
以上是关于使用 AFNetworking 的 enqueueBatchOfHTTPRequestOperations 失败时如何重新添加操作的主要内容,如果未能解决你的问题,请参考以下文章
有没有办法使用wp_enqueue_script直接添加JavaScript?
Retrofit 中的 Enqueue 方法不会在 Fragment 中加载数据
php [Debug enqueue scripts]快速调试,列出所有入队脚本。 #WordPress #enqueue
php 在Wordpress中使用'wp_enqueue_scripts'操作将Vue.js排入队列