• 跟踪 twisted 里deferred 的Callback


                     twisted 提供了 deferred 机制,而关键点就是回调。通过查看deferred 源码 (version 8.2.0)我们可以 看到

    deferred的addCallback是怎么工作的,以及相关的操作流程。 一个deferred 有一对回调链,一条处理正确的结果,一条处理错误的结果,addCallbacks 与 addCallback ,addBoth 函数则是向这对回调链里添加函数,addCallback 后,deferred 是怎么做的呢,我们看源码:

            

    def addCallbacks(self, callback, errback=None,
                         callbackArgs=None, callbackKeywords=None,
                         errbackArgs=None, errbackKeywords=None):
            """Add a pair of callbacks (success and error) to this Deferred.
    
            These will be executed when the 'master' callback is run.
            """
            assert callable(callback)
            assert errback == None or callable(errback)
            cbs = ((callback, callbackArgs, callbackKeywords),
                   (errback or (passthru), errbackArgs, errbackKeywords))
            self.callbacks.append(cbs)
    
            if self.called:
                self._runCallbacks()
            return self
    
    def addCallback(self, callback, *args, **kw):
            """Convenience method for adding just a callback.
    
            See L{addCallbacks}.
            """
            
            return self.addCallbacks(callback, callbackArgs=args,
                                     callbackKeywords=kw)
                 

    addCallback第二个参数是要添加的函数,第三个参数是要传递给回调函数的参数,第四个是要传递给回调函数
    的关键字,然后,addCallback里调用了addCallbacks 。 我们可以看到,在deferred初始化 时,这对回调链self.callbacks 是空的 

    def __init__(self):
            self.callbacks = [] 
            if self.debug:
                self._debugInfo = DebugInfo()
                self._debugInfo.creator = traceback.format_stack()[:-1]
            cbs = ((callback, callbackArgs, callbackKeywords),
                   (errback or (passthru), errbackArgs, errbackKeywords))
            self.callbacks.append(cbs)

     看addCallbacks源码,你会发现, 如果没有指定要添加的errback 时,errback 则是pass-through 的。这时,这对回调函数就会被添加到回调链的尾, 效果如图所示:

                                                                

                             

                当调用一个回调函数时,deferred 又会怎么做呢?假设当前调用的是 callback:

                 

    def callback(self, result):
            """Run all success callbacks that have been added to this Deferred.
    
            Each callback will have its result passed as the first
            argument to the next; this way, the callbacks act as a
            'processing chain'. Also, if the success-callback returns a Failure
            or raises an Exception, processing will continue on the *error*-
            callback chain.
            """
            assert not isinstance(result, Deferred)
            self._startRunCallbacks(result)
                  看作者的注释,deferred 把上一个回调函数的结果result传递给 _startRunCallbacks:

    def _startRunCallbacks(self, result):
            if self.called:
                if self.debug:
                    if self._debugInfo is None:
                        self._debugInfo = DebugInfo()
                    extra = "
    " + self._debugInfo._getDebugTracebacks()
                    raise AlreadyCalledError(extra)
                raise AlreadyCalledError
            if self.debug:
                if self._debugInfo is None:
                    self._debugInfo = DebugInfo()
                self._debugInfo.invoker = traceback.format_stack()[:-2]
            self.called = True
            self.result = result 
            if self.timeoutCall:
                try:
                    self.timeoutCall.cancel()
                except:
                    pass
    
                del self.timeoutCall
            self._runCallbacks()


                       但这时还没有真正调用了我们刚才添加的回调函数,在这个_startRunCallbacks 里是找不到回调链
    “self.callbacks ”的字眼的。这个函数是“开始执行回调函数”,对执行之前处理了一些事务,但它最后调用了
    _runCallbacks:

          

    def _runCallbacks(self):
            if self._runningCallbacks:
                # Don't recursively run callbacks
                return
            if not self.paused:
                while self.callbacks:
                    item = self.callbacks.pop(0) 
                    callback, args, kw = item[   
                        isinstance(self.result, failure.Failure)] 
                    args = args or ()            
                    kw = kw or {}               
    
                    try:
                        self._runningCallbacks = True
                        try:
                            self.result = callback(self.result, *args, **kw) 
                        finally:                                             
                            self._runningCallbacks = False                
                        if isinstance(self.result, Deferred):                
                            # note: this will cause _runCallbacks to be called
                            # recursively if self.result already has a result.
                            # This shouldn't cause any problems, since there is no
                            # relevant state in this stack frame at this point.
                            # The recursive call will continue to process
                            # self.callbacks until it is empty, then return here,
                            # where there is no more work to be done, so this call
                            # will return as well.
                            self.pause()
                            self.result.addBoth(self._continue)
                            break
                    except:
                        self.result = failure.Failure()
    
            if isinstance(self.result, failure.Failure):
                self.result.cleanFailure()
                if self._debugInfo is None:
                    self._debugInfo = DebugInfo()
                self._debugInfo.failResult = self.result
            else:
                if self._debugInfo is not None:
                    self._debugInfo.failResult = None

           self.callbacks.pop(0)                                                       #弹出回调链里的第一对回调函数,
        callback, args, kw = item[   
                        isinstance(self.result, failure.Failure)]            #根据self.result是否为 failure.Failure类型,来选择回调函数
                                                                                         
         self.result = callback(self.result, *args, **kw)                #这才真正执行了回调函数并把执行结果 作为参数传递给下                                                                                            #一个回调函数


        通过作者的注释,我们可以看到,当执行完回调函数之后,
    (1)若self.result 为deferred,即如果回调函数返回一个新的deferred,则当前的deferred(外部deferred)会

             暂停下来,去执行新的deferred(内部deferred)里的回调函数,直到内部deferred把控制权转交给外部  
             deferred,如图:

                                
            

                  看代码:

                            self.pause()
                            self.result.addBoth(self._continue)
                         而addBoth会调用addCallbacks,  addCallbacks 则调用_runCallbacks,

    def addBoth(self, callback, *args, **kw):
            """Convenience method for adding a single callable as both a callback
            and an errback.
    
            See L{addCallbacks}.
            """
            return self.addCallbacks(callback, callback,
                                     callbackArgs=args, errbackArgs=args,
                                     callbackKeywords=kw, errbackKeywords=kw)
      
    def addCallbacks(self, callback, errback=None,
                         callbackArgs=None, callbackKeywords=None,
                         errbackArgs=None, errbackKeywords=None):
            """Add a pair of callbacks (success and error) to this Deferred.
    
            These will be executed when the 'master' callback is run.
            """
            assert callable(callback)
            assert errback == None or callable(errback)
            cbs = ((callback, callbackArgs, callbackKeywords),
                   (errback or (passthru), errbackArgs, errbackKeywords))
            self.callbacks.append(cbs)
    
            if self.called:
                self._runCallbacks()
            return self


              调用顺序为:
              addBoth --> addCallbacks --> _runCallbacks, 如此递归执行。
    (2)若self.result 不为deferred,则执行下一个回调函数,并把self.result 传递给下一个回调函数,直到self.result为              空。整个跟踪过程就到这里把!


         参考:         
            http://twistedmatrix.com/trac/browser/tags/releases/twisted-.2.0/twisted/internet/defer.py
            http://krondo.com/?page_id=1327
            http://blog.sina.com.cn/s/blog_704b6af70100py9n.html 
       

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    55域TLV说明
    iOS开发之指定UIView的某几个角为圆角
    常逛的博客
    猿题库 iOS 客户端架构设计
    NSData
    base64编码
    RSA算法原理
    无法安装64位版本的office因为在您的pc
    mysql导出导入数据
    设置mysql的字符集
  • 原文地址:https://www.cnblogs.com/Rex7/p/4752581.html
Copyright © 2020-2023  润新知