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]; } 

但是我得到一个错误,因为第一个操作在另一个开始之前没有完全完成。

在检查日志时,似乎像这样执行:

  1. REST操作1 – 请求映射
  2. REST操作2 – 请求映射
  3. REST操作3 – 请求映射
  4. REST操作1 – HTTP调用和响应映射
  5. REST操作2 – HTTP调用和响应映射
  6. 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];