1

我正在使用 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 中做到这一点?

4

4 回答 4

1

问题

RestKitNSOperation对一个 REST 操作使用多个,因此所有请求映射将首先与问题中的代码一起排队。因此,当执行第一个请求映射并将实际 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;
        }
    }
}
于 2013-09-25T07:20:48.907 回答
0

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

于 2014-08-15T05:27:38.457 回答
0

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

这种异步问题可以通过“Promise”轻松解决(请在此 wiki 中阅读更多信息:Futures and Promises以获得一般说明)。

“Promise”表示异步方法的最终结果。最终它会变成您等待的值或错误。

您可以“链接”此类异步方法,以保证仅在第一个方法成功完成时才调用“下一个”方法。而且,还有一种方法可以“捕获”可能从异步方法“抛出”的错误。

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

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

注意,这是一个异步方法。它立即返回一个“待定”的承诺。NSOperation当您必须在包装器方法中实现的操作完成时,承诺最终会“解决” 。

现在,为了在第一个操作完成时“继续”下一个操作,您可以使用如下所示定义一个延续:then

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

注意:您可以使用 aNSOperationQueue来控制您的程序应该同时执行多少个请求。上面用 promise 定义的延续NSOperationQueue. 也就是说,您可以使用NSOperationQueue配置为执行例如四个并发操作的相同操作,并且可以并行执行任何其他不相关的 REST 操作,而不会中断上述“序列化”延续的控制流。

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

于 2014-08-15T06:09:02.697 回答
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];
于 2016-11-04T12:07:50.130 回答