內联回调
前面的章节已经提到了Python中的一个重要功能「生成器」的概念,而且生成器也是Python实现异步操作的基础。生成器不仅可以根据步进向外抛出值,还可以接受外部传来的值。例如以下示例:
def generator():
val = 0
while val < 30:
val = yield val
print('done')
gen = generator()
print(gen.next())
print(gen.send(20))
print(gen.send(29))
print(gen.send(31))
yield
语句是一个计算值的表达式,v = yield n
可以在迭代生成器时向外抛出n的值,并将外部调用.send()
方法的参数赋予v。并且在生成器内部还可以使用raise
抛出异常。
回顾至此,生成器是不是与Deferred十分相似。如果将生成器假设为一个Deferred对象,那么其中每个回调都会被yield
分隔,每一个yield
表达式的值就是下一个回调的结果,就像是以下示例中那样。
def a_deferred(arg1, arg2):
# 第一个callback
b = b * arg1
b2 = some_function(b)
result = yield b
# 第二个callback
f = result + b
result = yield some_function2()
# 第三个callback
try:
some_function3(result)
except SomeError:
handle_error(arg2)
Twisted中提供了一个名为inlineCallbacks
的修饰器,用来修饰一个生成器,将生成器转化为一系列异步回调,该修饰器位于twisted.internet.defer
包中。当调用一个由inlineCallbacks
修饰的生成器时,不需要手动调用send
或者raise
,修饰器会完成全部操作并保证生成器运行结束。如果生成器使用yield
抛出一个非Deferred值,那么生成器会立刻继续向下迭代。但如果生成器抛出一个Deferred,那么生成器就会等待Deferred对象被激活并返回,如果Deferred被激活后产生异常,那么yield
就会抛出异常,但这个异常只是普通的Exception,而不是Failure。
被inlineCallbacks
修饰的生成器在调用时,会得到一个Deferred对象,这个Deferred对象并不是生成器中yield
生成的Deferred。
Deferred在被激活后可以通过.cancel()
方法取消掉。调用.cancel()
方法会忽略后续的任何callback
和errback
。