在PromiseKit中,里面涉及了很多的递归操作,而递归操作,对于大部分人理解起来都是比较麻烦的(包括我),而github中一些高上大的第三方库,无一不涉及了很漂亮的递归操作,因此理解递归操作是很必要的。如果想成为尽可能优秀的程序猿。
递归操作:自己调用自己,不停的压栈,最后出栈。(说的简单,但是还是理解起来还是比较复杂的)
我们来接着看看PromiseKit的递归操作,看看它的链式结构式怎么样实现的。
相信在上一章就可以了解到,then操作最后返回的是一个新的PMKPromise,然后返回的PMKPromise实例可以再次调用then方法,这就是一个链式结构了(如下图)。很简单。如果仅仅是这种递归,那么就没必要写这篇了。
来仔细看看它内部的递归操作,了解它最后是如何进行这么多then得调用执行的,(它不是立刻调用then就执行了block的函数体,而是在之后的特定情况才执行的,比如UIAlertView 是在点击按钮的情况下进行执行的),还有看看它的值传递是如何进行的。
废话不多说先贴代码:
resolved:pending 函数里面的
dispatch_barrier_sync(_promiseQueue, ^{
if ((result = _result))
return;
__block PMKPromiseFulfiller resolver;
next = [PMKPromise new:^(PMKPromiseFulfiller fulfill, PMKPromiseRejecter reject) {
resolver = ^(id o){
if (IsError(o)) reject(o); else fulfill(o);
};
}];
[_handlers addObject:^(id value){
mkpendingCallback(value, next, q, block, resolver);
}];
});
和一个PMKRsolve函数
static void PMKResolve(PMKPromise *this, id result) {
void (^set)(id) = ^(id r){
NSArray *handlers = PMKSetResult(this, r);
for (void (^handler)(id) in handlers)
handler(r);
};
if (IsPromise(result)) {
PMKPromise *next = result;
dispatch_barrier_sync(next->_promiseQueue, ^{
id nextResult = next->_result;
if (nextResult == nil) { // ie. pending
[next->_handlers addObject:^(id o){
PMKResolve(this, o);
}];
} else
set(nextResult);
});
} else
set(result);
}
看到,set的block块执行的操作是遍历执行所有的储存在_handlers的handler的block块,还会把设置PMKResolved的result值,然后清空所有存储的_handler的block块。这是一个主体的块,能够让我们的then中得block合理的执行,这个在上一章节已经说过了。
下面便是一个主体的递归操作了,下面看看这个递归的操作是怎么样的:
1.判断是否 result 是 PMKResolved
2.如果不是PMKResolved,则调用set的block块(参数是Result)
3.如果是PMKResolved,则判断result的nextResult,判断它是否是PMKResolved
4.如果不是PMKResolved,则调用set的block块(参数是nextResult)
5.如果是PMKResolved,则回到1
这是整个递归的过程,打开整个无线循环的操作是2和4.
如果是UIAlertView实例,则直接会调用4的操作了。这样就是最简单的执行过程了。
我们想想,如果then后面接了好几个then,那么这个执行回事怎么样的,每个PMKResolved都会将他的handler执行完成,这样每个then中得block块就执行了,
dispatch_barrier_sync这个函数,保证了它是顺序执行的。那么它执行的顺序是不是就是类似于我们一行一行代码在执行一个个then中得block块了。至于值传递,我们也再上面说到了。这里就不在强调了。
最后递归比较难以理解,但是认真去解读的话还是可以的,在国外,很多高校都是以lisp或者haskell这样的函数式语言来接触编程的,有的有scheme这种语言的课程,这些语言的主要思想就是递归。因此递归还是在他们深深的脑海里的。许多情况下递归效率很高,代码很简洁。但是对于我们来说还是在不熟悉的情况下少用为妙。我也尝试学学这样一门语言,进行下头脑风暴。