Twisted中的Deferred对象实现

主要思路是维护一个列表[(callback1,errback1),(callback2,errback2),…]
每次从最前面取一个callback/errback对,然后依次运行,把运行结果放在current.result结果中传给下一个callback/errback对。如果发生错误就返回一个failure对象,判断之后执行errback

实现嵌套deferred的关键是[chain]列表
chain这个列表用来存放deferred对象
在两层(内外)deferred的情况下外层Deferred和内层Deferred的情况如下:
外层chain:[外层deferred]
内层最终chain:[内层deferred,外层deferred]
外层遇到内层Deferred的时候把自己打包放进内层对象的callback对列表中,用_CONTINUE标识。然后自己暂停运行。
内层被激活后,首先运行内层的回调,运行结束后,就会遇到_CONTINUE标识的外层deferred,把它放进chain。因为chain是一个循环,所以接着执行外层剩下的回调。内层的chain链经过了 [内] -》[内,外]-》[内]-》[]的过程。在内层Deferred的_runCallbacks函数中运行完外层剩余回调函数。
这么写是为了避免递归。

参考:https://blog.csdn.net/u012592285/article/details/51530810

class Deferred:
    called = False # 是一个初始化false为信号量,一旦callback和errback调用之后就置true
    paused = False #计数器,当pause大于0(或者为true?)的话callback或者是errback的调用会被暂停。
    _debugInfo = None
    _suppressAlreadyCalled = False # 是一个很重要的标志,用于deferred的取消机制,当deferred对象没有canceller并且已经被取消了(cancel方法被调用之后),该标志置为True,否则为False。

    _runningCallbacks = False  #_runningCallbacks是一个标志。当deferred对象的回调链正处于执行状态时为True,这个标志用于阻止_runCallbacks对象的递归调用。
    debug = False

    _chainedTo = None # 用于嵌套deferred,如果一个deferred对象需要等待另一个deferred对象的值的话,_chainedTo属性将指向 那个deferred对象。

    def __init__(self, canceller=None):
        self.callbacks = []
        self._canceller = canceller
        if self.debug:
            self._debugInfo = DebugInfo()
            self._debugInfo.creator = traceback.format_stack()[:-1]


    def addCallbacks(self, callback, errback=None,
                     callbackArgs=None, callbackKeywords=None,
                     errbackArgs=None, errbackKeywords=None):
        #####主要是通过这个函数添加回调链到self.callbacks这个列表中

    def callback(self, result):
        assert not isinstance(result, Deferred)
        self._startRunCallbacks(result)


    def errback(self, fail=None):
        if fail is None:
            fail = failure.Failure(captureVars=self.debug)
        elif not isinstance(fail, failure.Failure):
            fail = failure.Failure(fail)

        self._startRunCallbacks(fail)

    def _runCallbacks(self):
        chain = [self]

        ### 维持一个待处理的deferred栈
        while chain:
            current = chain[-1]

            finished = True
            current._chainedTo = None
            while current.callbacks:
                item = current.callbacks.pop(0)
                callback, args, kw = item[
                    isinstance(current.result, failure.Failure)]
                ###这里判断了一下回调链中回调函数的执行有没有出错。如果出错了,执行下一步的errback
                ###如果没有出错,执行下一步的callback
                    
                args = args or ()
                kw = kw or {}

                # Avoid recursion if we can.
                if callback is _CONTINUE:
                # 实现嵌套deferred的关键步骤
                # 这里,内层deferred的回调已经执行完毕
                # 接下来要执行被暂停的外层deferred剩下的回调。
                # 将里层的运行结果交给外层,将外层deferred标为继续执行并重新添加到deferred链中
                    # Give the waiting Deferred our current result and then
                    # forget about that result ourselves.
                    chainee = args[0] #获得外层Deferred对象
                    chainee.result = current.result
                    current.result = None
                    # Making sure to update _debugInfo
                    if current._debugInfo is not None:
                        current._debugInfo.failResult = None
                    chainee.paused -= 1
                    chain.append(chainee)
                    # Delay cleaning this Deferred and popping it from the chain
                    # until after we've dealt with chainee.
                    finished = False
                    break # break之后开始执行外层Deferred的接下来回调

                try:
                    current._runningCallbacks = True
                    try:
                        current.result = callback(current.result, *args, **kw)
                        ###执行回调,回调函数的结果保存在result中。
                    finally:
                        current._runningCallbacks = False
                except:
                    # Including full frame information in the Failure is quite
                    # expensive, so we avoid it unless self.debug is set.
                    current.result = failure.Failure(captureVars=self.debug)
                else:
                    ####遇到了嵌套的情况,在这里把它塞到内层Deferred的回调链中
                    if isinstance(current.result, Deferred):
                        # The result is another Deferred.  If it has a result,
                        # we can take it and keep going.
                        resultResult = getattr(current.result, 'result', _NO_RESULT)
                        if resultResult is _NO_RESULT or isinstance(resultResult, Deferred) or current.result.paused:
                            # Nope, it didn't.  Pause and chain.
                            current.pause()
                            current._chainedTo = current.result
                            # Note: current.result has no result, so it's not
                            # running its callbacks right now.  Therefore we can
                            # append to the callbacks list directly instead of
                            # using addCallbacks.
                            current.result.callbacks.append(current._continuation())
                            break
                        else:
                            # Yep, it did.  Steal it.
                            current.result.result = None
                            # Make sure _debugInfo's failure state is updated.
                            if current.result._debugInfo is not None:
                                current.result._debugInfo.failResult = None
                            current.result = resultResult
                            
            if finished:
                if isinstance(current.result, failure.Failure):
                    current.result.cleanFailure()
                    if current._debugInfo is None:
                        current._debugInfo = DebugInfo()
                    current._debugInfo.failResult = current.result
                else:
                    if current._debugInfo is not None:
                        current._debugInfo.failResult = None

                # This Deferred is done, pop it from the chain and move back up
                # to the Deferred which supplied us with our result.
                chain.pop()


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值