RestKit – 一次处理一个REST操作
我正在使用RestKit 0.20.3,并且需要按照一定的顺序完成一些REST操作( 来自一个REST操作的响应需要包含在下一个的请求参数映射中 )。
我试着设置队列来处理一次这样的操作:
RKObjectManager.sharedManager.operationQueue.maxConcurrentOperationCount = 1;
并添加这样的操作:
for (id insertedObject in insertedObjects) { [RKObjectManager.sharedManager postObject:insertedObject path:nil parameters:nil success:nil failure:nil]; }
但是我得到一个错误,因为第一个操作在另一个开始之前没有完全完成。
在检查日志时,似乎像这样执行:
- REST操作1 – 请求映射
- REST操作2 – 请求映射
- REST操作3 – 请求映射
- REST操作1 – HTTP调用和响应映射
- REST操作2 – HTTP调用和响应映射
- REST操作3 – HTTP调用和响应映射
我已经尝试设置操作依赖关系,但这没有什么差别。
我需要一次完成一个REST操作。 我如何在RestKit中做到这一点?
问题
RestKit对一个REST操作使用多个NSOperation
,所以所有的请求映射将首先与问题中的代码进行排队。 所以,当第一个请求映射被执行并且排队实际的HTTP请求时,它会在前两个请求映射操作之后排队。
解
在第一个完成后排队下一个操作。
recursion示例:
- (void)sync { NSArray *objectsToPostInOrder = ...; for (id objectToPost in objectsToPostInOrder) { [RKObjectManager.sharedManager postObject:objectToPost path:nil parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) { // Proceed with next if everything went OK [self sync]; } failure:^(RKObjectRequestOperation *operation, NSError *error) { // Don't continue posting as they are dependent on each other [MyHUD showErrorWithStatus:error.localizedDescription]; }]; return; } } }
我设法通过定义一个自定义的asynchronous NSOperation,它使用RestKit的对象获取,并没有表明它在RestKit的成功/失败块执行之前完成。 然后将这些自定义操作添加到maxConcurrentOperationCount设置为1的单独队列中(而不是RestKit的操作队列),或者可以根据需要定义操作间依赖关系。
一个更老的问题,但一个常见的问题:
这种asynchronous问题可以通过“Promise”轻松解决(请阅读本wiki的更多内容: 期货和承诺以获得一般指导)。
“Promise”表示asynchronous方法的最终结果。 最终它变成你等待的价值或错误。
你可以用这种方式来“链接”这样的asynchronous方法,以保证只有在第一个成功完成时才调用“next”方法。 而且,还有一种方法可以“捕捉”可能从asynchronous方法“抛出”的错误。
首先,你需要把调用请求的NSOperation
包装成一个返回promise的asynchronous方法:
- (Promise*) performRequestWithParams(NSDictionary* params);
请注意,这是一个asynchronous方法。 它立即返回一个“待定”的承诺。 当NSOperation
完成操作时,最终的承诺是“解决”,你必须在包装方法中实现。
现在,当第一次完成时,为了“继续”下一个操作,可以使用如下所示定义一个继续 :
Promise* promise = [self performRequestWithParams:params]; promise.then(^id(NSArray* result) { // We enter here, when the 1. REST op finished successfully: // note: here, `result` is the _result_ of the async operation above // which was a JSON returned from the service and parsed into an array. // Obtain a value from the result: id x = result[0][@"someKey"]; // Create a new JSON representation which is the input for the next REST operation: NSDictionary* params = ...; // Now, invoke the 2. REST op asynchronously: return [self performRequestWithParams:params]; }, nil) .then(^id(NSArray* result) { // We enter here, when the 2. REST op finished successfully: id x = result[0][@"someKey"]; // obtain a value from some dictionary NSDictionary* params = ...; // create a new JSON // Now, invoke the next async method: return [self performRequestWithParams:params]; }, nil) ... // 3., 4., ... add more REST operations // In case of an error in *any* of the operations above, let us "catch" it here: .then(nil, ^id(NSError* error){ NSLog(@"Error: %@", error); });
注意:你可以使用一个NSOperationQueue
来控制你的程序应该同时执行多less个请求。 上面定义的延续与NSOperationQueue
的约束正交 。 也就是说,你可以使用相同的NSOperationQueue
,这个NSOperationQueue
被configuration为执行例如四个并发操作,并且可以并行执行任何其他不相关的REST操作,而不会中断上面的“序列化”继续的控制stream。
有一些Promise图书馆。 我是其中之一的作者。 该项目是GitHub上提供的开放源码: RXPromise 。
到目前为止,我工作得很好。
AFRKHTTPClient *client = [[AFRKHTTPClient alloc] initWithBaseURL:self.baseUrl]; client.operationQueue.maxConcurrentOperationCount = 1; RKObjectManager *objectManager = [[RKObjectManager alloc] initWithHTTPClient:client]; objectManager.operationQueue.maxConcurrentOperationCount = 1; [RKObjectManager setSharedManager:objectManager];
- UITableView与NSFetchedResultsController不会第二次加载
- 生成失败,错误命令/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc
- Xcode 4核心数据:如何使用数据模型编辑器中创build的提取属性
- NSFetchRequest核心数据Swift 3向后兼容
- 请求成员tableView不是结构或联合
- 在创build新对象时查询特定属性的核心数据,如果存在,则返回该对象;如果不存在,则创build一个新的对象
- 如何将来自Core Data,iOS dev的结果进行分组
- 使用内置的CoreData选项在外部位置存储Blob
- 核心数据encryption