1
<?xml version="1.0" encoding="utf-8"?><!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'><html lang="en" xmlns="http://www.w3.org/1999/xhtml">
3
<title>Twisted Documentation: Asynchronous Responses</title>
4
<link href="../stylesheet.css" rel="stylesheet" type="text/css"/>
8
<h1 class="title">Asynchronous Responses</h1>
9
<div class="toc"><ol/></div>
13
<p>In all of the previous examples, the resource examples presented generated
14
responses immediately. One of the features of prime interest of Twisted Web,
15
though, is the ability to generate a response over a longer period of time while
16
leaving the server free to respond to other requests. In other words,
17
asynchronously. In this installment, we'll write a resource like this.</p>
19
<p>A resource that generates a response asynchronously looks like one that
20
generates a response synchronously in many ways. The same base class, <code class="API"><a href="http://twistedmatrix.com/documents/10.0.0/api/twisted.web.resource.Resource.html" title="twisted.web.resource.Resource">Resource</a></code>, is used either way; the
21
same render methods are used. There are three basic differences, though.</p>
23
<p>First, instead of returning the string which will be used as the body of the
24
response, the resource uses <code class="API"><a href="http://twistedmatrix.com/documents/10.0.0/api/twisted.web.http.Request.write.html" title="twisted.web.http.Request.write">Request.write</a></code>. This method can be called
25
repeatedly. Each call appends another string to the response body. Second, when
26
the entire response body has been passed to <code>Request.write</code>, the
27
application must call <code class="API"><a href="http://twistedmatrix.com/documents/10.0.0/api/twisted.web.http.Request.finish.html" title="twisted.web.http.Request.finish">Request.finish</a></code>. As you might expect from the
28
name, this ends the response. Finally, in order to make Twisted Web not end the
29
response as soon as the render method returns, the render method must return
30
<code>NOT_DONE_YET</code>. Consider this example:</p>
32
<pre class="python"><p class="py-linenumber"> 1
44
</p><span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">web</span>.<span class="py-src-variable">resource</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">Resource</span>
45
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">web</span>.<span class="py-src-variable">server</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">NOT_DONE_YET</span>
46
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">reactor</span>
48
<span class="py-src-keyword">class</span> <span class="py-src-identifier">DelayedResource</span>(<span class="py-src-parameter">Resource</span>):
49
<span class="py-src-keyword">def</span> <span class="py-src-identifier">_delayedRender</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">request</span>):
50
<span class="py-src-variable">request</span>.<span class="py-src-variable">write</span>(<span class="py-src-string">"Sorry to keep you waiting."</span>)
51
<span class="py-src-variable">request</span>.<span class="py-src-variable">finish</span>()
53
<span class="py-src-keyword">def</span> <span class="py-src-identifier">render_GET</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">request</span>):
54
<span class="py-src-variable">reactor</span>.<span class="py-src-variable">callLater</span>(<span class="py-src-number">5</span>, <span class="py-src-variable">self</span>.<span class="py-src-variable">_delayedRender</span>, <span class="py-src-variable">request</span>)
55
<span class="py-src-keyword">return</span> <span class="py-src-variable">NOT_DONE_YET</span>
58
<p>If you're not familiar with reactor.<code class="API"><a href="http://twistedmatrix.com/documents/10.0.0/api/twisted.internet.interfaces.IReactorTime.callLater.html" title="twisted.internet.interfaces.IReactorTime.callLater">callLater</a></code>, all you really
59
need to know about it to understand this example is that the above usage of it
60
arranges to have <code>self._delayedRender(request)</code> run about 5 seconds
61
after <code>callLater</code> is invoked from this render method and that it
62
returns immediately.</p>
64
<p>All three of the elements mentioned earlier can be seen in this example. The
65
resource uses <code>Request.write</code> to set the response body. It uses
66
<code>Request.finish</code> after the entire body has been specified (all with
67
just one call to write in this case). Lastly, it returns
68
<code>NOT_DONE_YET</code> from its render method. So there you have it,
69
asynchronous rendering with Twisted Web.</p>
71
<p>Here's a complete rpy script based on this resource class (see the <a href="rpy-scripts.html" shape="rect">previous example</a> if you need a reminder about rpy
74
<pre class="python"><p class="py-linenumber"> 1
88
</p><span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">web</span>.<span class="py-src-variable">resource</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">Resource</span>
89
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">web</span>.<span class="py-src-variable">server</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">NOT_DONE_YET</span>
90
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">reactor</span>
92
<span class="py-src-keyword">class</span> <span class="py-src-identifier">DelayedResource</span>(<span class="py-src-parameter">Resource</span>):
93
<span class="py-src-keyword">def</span> <span class="py-src-identifier">_delayedRender</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">request</span>):
94
<span class="py-src-variable">request</span>.<span class="py-src-variable">write</span>(<span class="py-src-string">"Sorry to keep you waiting."</span>)
95
<span class="py-src-variable">request</span>.<span class="py-src-variable">finish</span>()
97
<span class="py-src-keyword">def</span> <span class="py-src-identifier">render_GET</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">request</span>):
98
<span class="py-src-variable">reactor</span>.<span class="py-src-variable">callLater</span>(<span class="py-src-number">5</span>, <span class="py-src-variable">self</span>.<span class="py-src-variable">_delayedRender</span>, <span class="py-src-variable">request</span>)
99
<span class="py-src-keyword">return</span> <span class="py-src-variable">NOT_DONE_YET</span>
101
<span class="py-src-variable">resource</span> = <span class="py-src-variable">DelayedResource</span>()
104
<p>Drop this source into a <code>.rpy</code> file and fire up a server using
105
<code>twistd -n web --path /directory/containing/script/.</code> You'll see that
106
loading the page takes 5 seconds. If you try to load a second before the first
107
completes, it will also take 5 seconds from the time you request it (but it
108
won't be delayed by any other outstanding requests).</p>
110
<p>Something else to consider when generating responses asynchronously is that
111
the client may not wait around to get the response to its
112
request. A <a href="interrupted.html" shape="rect">subsequent example</a> demonstrates how
113
to detect that the client has abandoned the request and that the server
114
shouldn't bother to finish generating its response.</p>
118
<p><a href="../index.html">Index</a></p>
119
<span class="version">Version: 10.0.0</span>
b'\\ No newline at end of file'