为什么不能两次调用Twisted的deferred?

7 投票
1 回答
712 浏览
提问于 2025-04-18 06:27

来自以下指南: http://krondo.com/blog/?p=1682

Deferreds(延迟对象)帮助我们避免了回调编程中的一个常见问题。当我们使用延迟对象来管理回调时,就不会犯同时调用回调和错误回调,或者调用回调二十七次的错误。我们可以尝试这样做,但延迟对象会立刻给我们抛出一个异常,而不是把我们的错误传递给回调本身。

有没有人能给我更好的解释?

我注意到无论如何它都不会工作,因为在这个教程中的大多数情况下,最后的回调也会调用 reactor.stop()。但为什么不应该调用一个延迟对象两次呢?这和再次调用一系列方法有什么不同呢?

1 个回答

7

一个 Deferred 代表了一个请求的结果,这个结果可能现在就能得到,也可能将来才能得到,但现在并不一定能得到。

结果通过 Deferred 的回调链 流动。比如,在一个同步程序中,你可能会看到这样的代码:

response_bytes = make_request(...)
response_dict = parse_json(response_bytes)
response_object = construct_object(response_dict)
return response_object.method()

如果把它转成返回一个 Deferred 的代码,应该是这样的:

response_bytes_later = make_request_async(...)
response_dict_later = response_bytes_later.addCallback(parse_json)
response_object_later = response_dict_later.addCallback(construct_object)
return response_object_later.addCallback(lambda response_object:
                                         response_object.method())

问为什么你不能触发(或者说“回调”)由 make_request_async 返回的 Deferred,就像问为什么你不能让 make_request 多次返回 来重新发起请求一样。如果你想在同步版本中再次发起请求,你必须再次调用 make_request(并得到一个新的结果)。如果你想在异步版本中再次发起请求,你必须再次调用 make_request_async(并得到一个新的 Deferred)。

撰写回答