內联回调

前面的章节已经提到了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()方法会忽略后续的任何callbackerrback