中断响应¶
前面的示例有一个资源,它异步生成响应,而不是在调用其 render 方法时立即生成。当异步生成响应时,就会出现客户端连接在响应生成之前丢失的可能性。在这种情况下,通常希望完全放弃响应生成,因为一旦数据生成,就无法对其进行任何操作。本示例演示了如何收到连接丢失的通知。
本示例将基于 异步响应示例,该示例只是(如果不是非常现实地)在固定延迟后生成响应。我们将扩展该资源,以便一旦客户端连接丢失,延迟事件就会被取消,并且响应永远不会生成。
本示例依赖的功能由另一个 Request
方法提供:notifyFinish
。此方法返回一个新的 Deferred,如果请求成功响应,它将使用 None
触发,否则将使用错误触发 - 例如,如果在发送响应之前连接丢失。
该示例以熟悉的方式开始,包括必要的 Twisted 导入和一个资源类,该类使用与之前相同的 _delayedRender
。
from twisted.web.resource import Resource
from twisted.web.server import NOT_DONE_YET
from twisted.internet import reactor
class DelayedResource(Resource):
def _delayedRender(self, request):
request.write(b"<html><body>Sorry to keep you waiting.</body></html>")
request.finish()
在定义 render 方法之前,我们将定义一个 errback(errback 是一个在发生错误时被调用的回调)。这将是附加到 Deferred
的 errback,该 Deferred
由 Request.notifyFinish
返回。它将取消对 _delayedRender
的延迟调用。
...
def _responseFailed(self, err, call):
call.cancel()
最后,render 方法将像以前一样设置延迟调用,并同样返回 NOT_DONE_YET
。但是,它还将使用 Request.notifyFinish
来确保在适当的情况下调用 _responseFailed
。
...
def render_GET(self, request):
call = reactor.callLater(5, self._delayedRender, request)
request.notifyFinish().addErrback(self._responseFailed, call)
return NOT_DONE_YET
请注意,由于 _responseFailed
需要对延迟调用对象的引用才能取消它,因此我们将该对象传递给了 addErrback
。传递给 addErrback
(或 addCallback
)的任何其他参数都将在 Failure
实例之后传递给 errback,该实例始终作为第一个参数传递。在这里传递 call
表示它将传递给 _responseFailed
,在那里它被期望和需要。
这涵盖了本示例中几乎所有代码。以下是整个示例,没有中断,作为 rpy 脚本 。
from twisted.web.resource import Resource
from twisted.web.server import NOT_DONE_YET
from twisted.internet import reactor
class DelayedResource(Resource):
def _delayedRender(self, request):
request.write(b"<html><body>Sorry to keep you waiting.</body></html>")
request.finish()
def _responseFailed(self, err, call):
call.cancel()
def render_GET(self, request):
call = reactor.callLater(5, self._delayedRender, request)
request.notifyFinish().addErrback(self._responseFailed, call)
return NOT_DONE_YET
resource = DelayedResource()
将此代码放入 example.rpy
中,使用 twistd -n web --path .
启动它,然后访问 http://localhost:8080/example.rpy 。如果您等待五秒钟,您将获得页面内容。如果您在五秒钟之前中断请求,例如通过按下 Escape 键(至少在 Firefox 中),那么您将看到可能是有史以来最无聊的演示 - 没有页面内容,并且服务器日志中没有任何内容。成功!