Twisted中奇怪的回调执行顺序?

时间:2011-11-22 01:29:22

标签: python twisted

请考虑以下代码:

from twisted.internet.defer import Deferred

d1 = Deferred()
d2 = Deferred()

def f1(result):
    print 'f1',

def f2(result):
    print 'f2',

def f3(result):
    print 'f3',

def fd(result):
    return d2

d1.addCallback(f1)
d1.addCallback(fd)
d1.addCallback(f3)

#/BLOCK====
d2.addCallback(f2)
d1.callback(None)
#=======BLOCK/

d2.callback(None)

这会输出我的期望:

f1 f2 f3

然而,当我将BLOCK中语句的顺序交换为

#/BLOCK====
d1.callback(None)
d2.addCallback(f2)
#=======BLOCK/

即。在将回调添加到d2之前触发d1,我得到:

f1 f3 f2

我不明白为什么解雇延迟的时间会影响回调执行顺序 这是Twisted的问题还是以某种方式有意义?

1 个答案:

答案 0 :(得分:3)

tl; dr - 当您从回调(d2)返回延迟(fd)时,它会被插入到任何延迟的回调链中({{1 }})名为d1。这是通过在fd上添加d1的回调链的延续作为回调来完成的,因此如果您在触发后d2 添加回调{{ 1}},在 d2的继续之后,它会在上加上。


我认为你错过了延迟不是异步的事实,它们只是一种在异步代码中链接回调和错误处理程序的更有条理的方式。回调在以后某个未指定的时间不会被调用,当延迟被触发时,它们被称为 。如果您希望以后使用此功能,则需要将呼叫与d1进行整合。

所以也许这使得答案更加明显:

  

我不明白为什么解雇延迟的时间会影响回调执行顺序。

如果您在之后更改回调,则会触发延迟。

您的代码说明

在第一个例子中:

  1. d1会导致reactor被解雇
  2. d1.callback(None)被调用(打印“f1”)
  3. d1被调用(返回f1
  4. 现在停止了,因为在fdd2之间d2d1 f1,但尚未被解雇。然后...

    1. f3会导致d2.callback(None)被解雇
    2. d2被调用(打印“f2”)
    3. f2的回调链恢复;所以调用d1(打印“f3”)
    4. 在第二个例子中

      1. f3会导致d1.callback(None)被解雇
      2. d1被调用(打印“f1”)
      3. f1被调用(返回fd
      4. 此处d2再次插入回调链中。这样做的方法是inserted in the callback chain作为d2的回调。因此,即使您在d2上明确添加f2作为回调,也会在d2的回调链的继续之后添加 。因此...

        1. d1导致d2.callback(None)被解雇;这导致d2的回调链继续,从...
        2. 开始
        3. d1被调用(打印“f3”)
        4. f3 它的链中的下一个回调是d2,所以......
        5. f2被调用(打印“f2”)