_inlineCallbacks详解

来源:互联网 发布:js注册界面源代码 编辑:程序博客网 时间:2024/05/17 07:53

twisted.defer的inlineCallbacks是个修饰符,其真正实现如下:

def inlineCallbacks(f):    def unwindGenerator(*args, **kwargs):        try:            gen = f(*args, **kwargs)        except _DefGen_Return:            raise TypeError(                "inlineCallbacks requires %r to produce a generator; instead"                "caught returnValue being used in a non-generator" % (f,))        if not isinstance(gen, types.GeneratorType):            raise TypeError(                "inlineCallbacks requires %r to produce a generator; "                "instead got %r" % (f, gen))        return _inlineCallbacks(None, gen, Deferred())    return mergeFunctionMetadata(f, unwindGenerator)
实际上真正调用的是_inlineCallbacks()函数,下面是该函数的详细分析

def _inlineCallbacks(result, g, deferred):    # waiting是用来控制递归的    waiting = [True, # waiting for result?                None] # result    while 1:        try:    # 触发下一个callback,执行结果有4种情况:    # 1)该callback返回一个非Deferred对象,那么回到顶部继续下一轮while,    #触发下下一个callback,而该非Deferred对象作为下下一个callback的参数;    # 2)执行该callback时触发了一个except,执行异常处理(如果是StopIteration,    #说明生成器执行完毕,不存在新的元素了);    # 3)该callback返回一个未执行完Deferred对象(表示该callback调用未执行完毕);    # 4)该callback返回一个执行完毕的Deferred对象(表示该callback调用已经执行完毕)    result = g.send(result)except StopIteration:    # fell off the end, or "return" statement    # deferred.callback(result=None): start processing the callback     # chain starting with the provided result.     # It will be send to the first callback or stored as finally one     # if not any further callback has been specialed yet.    return deferred    deferred.callback(None) ...if isinstance(result, Deferred):    # a deferred was yielded, get the result.    def gotResult(r):        # 如果waiting[]为True,说明是result是个已经执行完毕的Deferred        # 然后gotResult()是在result.addBoth()中被调用执行的        # 那么通过waiting[1]保存结果,不进行递归,而是继续执行while循环        if waiting[]:            waiting[] = False            waiting[1] = r        else:            _inlineCallbacks(r, g, deferred)    # 当添加result Deferred对象的事件回调时,如果该result是个已经执行完毕的Deferred    #(Deferred对象的callback调用已经执行完毕),那么在addBoth()函数内    # 将直接执行事件回调函数gotResult(),并走gotResult()的if语句,然后又继续回到顶部    # 的while循环触发紧接着的下一个callback调用;如果该result是个未执行完毕的    # Deferred(Deferred对象的callback调用未执行完毕),那么添加该result的    # 完成触发事件gotResult,并执行result.addBoth()下面的if语句,将waiting[]修改    # 为False,然后执行return返回退出while循环。在接下来的时间中,    # 一旦该result对于的callback执行完毕,将触发该result添加的gotResult()回调,    # 并执行_inlineCallbacks(),然后继续执行callback链中的下一个callback调用。    result.addBoth(gotResult)    if waiting[]:waiting[] = Falsereturn deferred    # 能执行到这里,说明addBoth()中直接执行了gotResult()函数,并将保存在    # waiting[1]中的结果保存到result中,然后回到顶部继续执行while循环    result = waiting[1]    # 为下一轮while循环做准备    waiting[] = True    waiting[1] = None    return deferred







0 0
原创粉丝点击