PromiseKit 1.7.3代码阅读

一、创建PMKPromise

PMKPromise new:
    PMKPromise promiseWithResolver:block
        block1(resolve);//执行

1

block1(PMKResolver resolve)
{
    id rejecter = ^(id error){
        if (error == nil) {
            error = NSErrorFromNil();
        } else if (IsPromise(error) && [error rejected]) {
            // this is safe, acceptable and (basically) valid
        } else if (!IsError(error)) {
            id userInfo = @{NSLocalizedDescriptionKey: [error description], PMKUnderlyingExceptionKey: error};
            error = [NSError errorWithDomain:PMKErrorDomain code:PMKInvalidUsageError userInfo:userInfo];
        }
        resolve(error);
    };

    id fulfiller = ^(id result){
        if (IsError(result))
            PMKLog(@"PromiseKit: Warning: PMKFulfiller called with NSError.");
        resolve(result);
    };

    block2(fulfiller, rejecter);
}

2

block2(PMKPromiseFulfiller fulfiller, PMKPromiseRejecter rejecter) {
    //程序员定制
    //调用fulfiller 或 rejecter
    //需要准备:result | error  
}

3

fulfiller | rejecter
    resolve(id)

4

resolve(id result) {    //result = NSError/id(PKMArray)/PMKPromise
    if (PMKGetResult(this))
        return PMKLog(@"PromiseKit: Warning: Promise already resolved");

    PMKResolve(this, result);
}

5

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

6

handler(r);    PMKPromise._handlers

二、问题:_handlers什么时候加入元素

.then(^(){});
这里有2步调用:

  1. .then 返回block
  2. (^(){}) 执行.then返回的block

block(id ourBlock)
self.thenOn(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ourBlock);

这里的语法与.then(^(){})相同,有2步调用:

  1. self.thenOn 返回block2
  2. (queue, ourBlock) 执行self.thenOn返回的block2
block2(q, ourBlock) 
{

    ourBlock = [ourBlock copy];

    __block PMKPromise *next = nil;

    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, ourBlock, resolver);
        }];
    });

    return next ?: mkresolvedCallback(result)(q, ourBlock);
}
mkpendingCallback(value, next, q, ourBlock, resolver);
mkpendingCallback(id result, PMKPromise *next, dispatch_queue_t q, id ourBlock, void (^resolve)(id)) 
{
    if (IsError(result))
        PMKResolve(next, result);
    else dispatch_async(q, ^{
        resolve(pmk_safely_call_block(ourBlock, result));
    });
}
pmk_safely_call_block(ourBlock, result)
{
    ourBlock(result[0], result[1], result[2]);
}

[TOC]

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 第一篇第二篇大概是把下载图片缓存图片的这个逻辑走完了,里面涉及好多类。 罗列一下 UIView+WebCache ...
    充满活力的早晨阅读 4,110评论 0 1
  • 简介 GCD(Grand Central Dispatch)是在macOS10.6提出来的,后来在iOS4.0被引...
    sunmumu1222阅读 4,363评论 0 2
  • 原文: 多线程编程4 - GCD 一、简介在iOS所有实现多线程的方案中,GCD应该是最有魅力的,因为GCD本身是...
    难却却阅读 1,209评论 0 0
  • 一、简介 在iOS所有实现多线程的方案中,GCD应该是最有魅力的,因为GCD本身是苹果公司为多核的并行运算提出的解...
    Alanxx阅读 2,738评论 0 1
  • 一、简介在iOS所有实现多线程的方案中,GCD应该是最有魅力的,因为GCD本身是苹果公司为多核的并行运算提出的解决...
    MYS_iOS_8801阅读 3,593评论 0 0