我目前正在开发一个库(RXPromise,其源代码在 GitHub 上),它使许多复杂的异步模式很容易实现。
以下方法使用一个类RXPromise
并生成 100% 异步的代码 - 这意味着绝对没有阻塞。“等待”将通过异步任务完成或取消时调用的处理程序来完成。
它还利用了一个NSArray
不属于该库的类别 - 但可以使用 RXPromise 库轻松实现。
例如,您的代码可能如下所示:
- (RXPromise*)asyncTestAbc
{
return [someThing retrieve:@"foo"]
.then(^id(id unused /*names?*/) {
// retrieve:@"foo" finished with success, now execute this on private queue:
NSArray* names = @[@"John", @"Mary", @"Peter", @"Madalena"];
return [names rx_serialForEach:^RXPromise* (id name) { /* return eventual result when array finished */
return [someObject lookupName:name] /* return eventual result of lookup's completion handler */
.thenOn(mainQueue, ^id(id result) {
assert(<we are on main thread>);
// A. Do something after a lookupName:name completes a few seconds later
return nil;
}, nil /*might be implemented to detect a cancellation and "backward" it to the lookup task */);
}]
},nil);
}
为了测试最终结果:
[self asyncTestAbc]
.thenOn(mainQueue, ^id(id result) {
// C. all `[someObject lookupName:name]` and all the completion handlers for
// lookupName, and `[someThing retrieve:@"foo"]` have finished.
assert(<we are on main thread>);
STAssertTrue(...);
}, id(NSError* error) {
assert(<we are on main thread>);
STFail(@"ERROR: %@", error);
});
该方法asyncTestABC
将完全按照您的描述进行 - 除了它是异步的。出于测试目的,您可以等到它完成:
[[self asyncTestAbc].thenOn(...) wait];
但是,您不能在主线程上等待,否则您会遇到死锁,因为asyncTestAbc
也会在主线程上调用完成处理程序。
如果您觉得这很有用,请索取更详细的解释!
注意:RXPromise 库仍在“进行中”。它可以帮助每个人处理复杂的异步模式。上面的代码使用了一个当前未提交给 GitHub 上的 master 的功能:thenOn
可以指定队列的属性,其中将执行处理程序。目前只有一个属性then
省略了处理程序应该运行的参数队列。除非另有说明,否则所有处理程序都在共享专用队列上运行。欢迎提出建议!