RestKit - 一次处理一个REST操作

时间:2013-09-24 23:47:53

标签: ios objective-c core-data restkit restkit-0.20

我正在使用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调用和响应映射
  7. 我已经尝试过设置操作依赖项,但这没有什么区别。

    我需要一次完成一个REST操作。我如何在RestKit中执行此操作?

4 个答案:

答案 0 :(得分:1)

<强>问题

RestKit对一个REST操作使用多个NSOperation,因此所有请求映射将首先与问题中的代码排队。因此,当执行第一个请求映射并对实际的HTTP请求进行排队时,它会在前两个请求映射操作之后排队。

<强>解

在第一个操作完成后对下一个操作进行排队。

递归示例:

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

答案 1 :(得分:0)

我设法通过定义一个自定义asynchronous NSOperation来使它工作,它使用RestKit的对象get并不表示在RestKit的成功/失败块执行之前它已完成。然后将这些自定义操作添加到单独的队列(而不是RestKit的操作队列)中,并将maxConcurrentOperationCount设置为1,或者您可以根据需要定义操作间依赖关系。

答案 2 :(得分:0)

一个较旧的问题,但是一个常见的反复出现的问题:

这种异步问题可以通过&#34; Promise&#34;轻松解决。 (请阅读本维基中的更多信息:Futures and Promises获取一般性说明。)

A&#34;承诺&#34;表示异步方法的最终结果。 最终它将成为您等待的值或错误。

你可以&#34;链&#34;这种异步方法的方式可以保证&#34; next&#34;方法仅在第一个成功完成时调用。并且,还有一种方法可以捕获&#34;可能已被抛出的错误&#34;来自异步方法。

首先,您需要将调用请求的NSOperation包装到一个返回promise的异步方法中:

- (Promise*) performRequestWithParams(NSDictionary* params);

注意,这是一个异步方法。它会立即返回&#34;待定&#34;诺言。承诺已经解决了#34;最终当操作按照你必须在包装器方法中实现的NSOperation完成时。

现在,为了&#34;继续&#34;在第一次完成后的下一个操作中,使用then定义 continuation ,如下所示:

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来控制程序应同时执行的请求数。使用上面的promise定义的continuation是正交NSOperationQueue的约束。也就是说,您可以使用配置为执行四个并发操作的相同NSOperationQueue,并且并行执行任何其他无关的REST操作而不会中断&#34;序列化&#34;的控制流程上面的延续。

周围有几个Promise库。我是其中之一的作者。该项目是GitHub上的开源代码:RXPromise

答案 3 :(得分:0)

到目前为止,对我来说效果很好。

AFRKHTTPClient *client = [[AFRKHTTPClient alloc] initWithBaseURL:self.baseUrl];
client.operationQueue.maxConcurrentOperationCount = 1;

RKObjectManager *objectManager = [[RKObjectManager alloc] initWithHTTPClient:client];
objectManager.operationQueue.maxConcurrentOperationCount = 1;
[RKObjectManager setSharedManager:objectManager];