我正在使用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操作。我如何在RestKit中执行此操作?
答案 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];