Deferred

Deferred是Twisted中处理回调的一种抽象机制。一个Deferred有一对回调链,一个处理正确的结果,另一个处理异常结果。我们可以通过向其中添加callbackerrback回调来使Deferred响应正确结果或者异常结果。

以下是一个只有一层回调的Deferred示例。

from twisted.internet.defer import Deferred
from twisted.python.failure import Failure


def success(res):
	print('A success chain')
	return res


def err_process(err):
	print('A Error occurred')


d = Deferred()
d.addCallbacks(success, err_process)
d.callback('success') # 调用处理正确结果的回调
d.errback(Failure(Exception('Some error'))) # 调用处理错误结果的回调,这里手工建立Failure对象
d.errback(Esception('Some error')) # 调用处理错误结果的回调,Deferred会将Exception对象自动转换为Failure对象

一个Deferred对象只允许被激活一次,也就是只允许调用一次.callback()方法。这是因为多次激活会导致多个回调同时出现,

下面再向Deferred中添加一层回调,并且跟Reactor结合起来。

from twisted.internet.defer import Deferred


def success(res):
	print('A success chain')
	return res


def err_process(err):
	print('A Error occurred')


def done(_):
	from twisted.internet import reactor
	reactor.stop()


d = Deferred()
d.addCallbacks(success, err_process)
d.addBoth(done) # 将回调同时添加到两条回调链上

from twisted.internet import reactor
reactor.callWhenRunning(d.callback, 'Success calling') # 当Reactor启动时调用指定函数,并传递给定的参数
reator.run()

在不使用Deferred时,重构异步函数相当困难,但是借助Deferred,可以通过修改回调链来重构应用。

Deferred提供了以下四个方法来将回调函数添加到回调链中。

\begin{itemize}

  • .addCallbacks(callback, errback),同时添加一对callbackerrback
  • .addCallback(callback),添加一个callback和一个直接返回第一个参数的直通函数。
  • .addErrback(errback),添加一个errback和一个直通函数。
  • .addBoth(function),将同一个回调函数同时添加到两条回调链中。 \end{itemize}

这里要注意的一个问题就是:在一个Deferred中,callbackerrback总是成对出现的,即便是仅添加一个callback或者errback,Deferred也会自动向另一条回调链中添加一个虚设的函数。

Deferred可以嵌套,可以在一个回调函数中返回一个Deferred,这样外层的Deferred会等待内部的Deferred激活并返回后继续执行。

Warning

注意:如果一个对象创建了一个Deferred,那么应该在其中对被创建的Deferred进行激活。