一个较老的问题,但一个常见的反复出现的问题:
这种异步问题可以通过“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。