~ntt-pf-lab/nova/monkey_patch_notification

« back to all changes in this revision

Viewing changes to vendor/Twisted-10.0.0/doc/web/howto/web-in-60/asynchronous-deferred.html

  • Committer: Jesse Andrews
  • Date: 2010-05-28 06:05:26 UTC
  • Revision ID: git-v1:bf6e6e718cdc7488e2da87b21e258ccc065fe499
initial commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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">
 
2
  <head>
 
3
<title>Twisted Documentation: Asynchronous Responses (via Deferred)</title>
 
4
<link href="../stylesheet.css" rel="stylesheet" type="text/css"/>
 
5
  </head>
 
6
 
 
7
  <body bgcolor="white">
 
8
    <h1 class="title">Asynchronous Responses (via Deferred)</h1>
 
9
    <div class="toc"><ol/></div>
 
10
    <div class="content">
 
11
<span/>
 
12
 
 
13
<p>The previous example had a <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> that generates its response
 
14
asynchronously rather than immediately upon the call to its render
 
15
method. Though it was a useful demonstration of the <code>NOT_DONE_YET</code>
 
16
feature of Twisted Web, the example didn't reflect what a realistic application
 
17
might want to do. This example introduces <code class="API"><a href="http://twistedmatrix.com/documents/10.0.0/api/twisted.internet.defer.Deferred.html" title="twisted.internet.defer.Deferred">Deferred</a></code>, the Twisted class which is used
 
18
to provide a uniform interface to many asynchronous events, and shows you an
 
19
example of using a <code>Deferred</code>-returning API to generate an
 
20
asynchronous response to a request in Twisted Web.</p>
 
21
 
 
22
<p><code>Deferred</code> is the result of two consequences of the asynchronous
 
23
programming approach. First, asynchronous code is frequently (if not always)
 
24
concerned with some data (in Python, an object) which is not yet available but
 
25
which probably will be soon. Asynchronous code needs a way to define what will
 
26
be done to the object once it does exist. It also needs a way to define how to
 
27
handle errors in the creation or acquisition of that object. These two needs are
 
28
satisfied by the <i>callbacks</i> and <i>errbacks</i> of a
 
29
<code>Deferred</code>. Callbacks are added to a <code>Deferred</code> with <code class="API"><a href="http://twistedmatrix.com/documents/10.0.0/api/twisted.internet.defer.Deferred.addCallback.html" title="twisted.internet.defer.Deferred.addCallback">Deferred.addCallback</a></code>; errbacks
 
30
are added with <code class="API"><a href="http://twistedmatrix.com/documents/10.0.0/api/twisted.internet.defer.Deferred.addErrback.html" title="twisted.internet.defer.Deferred.addErrback">Deferred.addErrback</a></code>. When the object
 
31
finally does exist, it is passed to <code class="API"><a href="http://twistedmatrix.com/documents/10.0.0/api/twisted.internet.defer.Deferred.callback.html" title="twisted.internet.defer.Deferred.callback">Deferred.callback</a></code> which passes it on to the
 
32
callback added with <code>addCallback</code>. Similarly, if an error occurs,
 
33
<code class="API"><a href="http://twistedmatrix.com/documents/10.0.0/api/twisted.internet.defer.Deferred.errback.html" title="twisted.internet.defer.Deferred.errback">Deferred.errback</a></code> is
 
34
called and the error is passed along to the errback added with
 
35
<code>addErrback</code>. Second, the events that make asynchronous code actually
 
36
work often take many different, incompatible forms. <code>Deferred</code> acts
 
37
as the uniform interface which lets different parts of an asynchronous
 
38
application interact and isolates them from implementation details they
 
39
shouldn't be concerned with.</p>
 
40
 
 
41
<p>That's almost all there is to Deferred. To solidify your new understanding,
 
42
now consider this rewritten version of DelayedResource which uses a
 
43
Deferred-based delay API. It does exactly the same thing as the <a href="asynchronous.html" shape="rect">previous example</a>. Only the implementation is
 
44
different.</p>
 
45
 
 
46
<p>First, the example must import that new API that was just mentioned, <code class="API"><a href="http://twistedmatrix.com/documents/10.0.0/api/twisted.internet.task.deferLater.html" title="twisted.internet.task.deferLater">deferLater</a></code>:</p>
 
47
 
 
48
<pre class="python"><p class="py-linenumber">1
 
49
</p><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-variable">task</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">deferLater</span>
 
50
</pre>
 
51
 
 
52
<p>Next, all the other imports (these are the same as last time):</p>
 
53
 
 
54
<pre class="python"><p class="py-linenumber">1
 
55
2
 
56
3
 
57
</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>
 
58
<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>
 
59
<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>
 
60
</pre>
 
61
 
 
62
<p>With the imports done, here's the first part of the
 
63
<code>DelayedResource</code> implementation. Again, this part of the code is
 
64
identical to the previous version:</p>
 
65
 
 
66
<pre class="python"><p class="py-linenumber">1
 
67
2
 
68
3
 
69
4
 
70
</p><span class="py-src-keyword">class</span> <span class="py-src-identifier">DelayedResource</span>(<span class="py-src-parameter">Resource</span>):
 
71
    <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>):
 
72
        <span class="py-src-variable">request</span>.<span class="py-src-variable">write</span>(<span class="py-src-string">&quot;Sorry to keep you waiting.&quot;</span>)
 
73
        <span class="py-src-variable">request</span>.<span class="py-src-variable">finish</span>()
 
74
</pre>
 
75
 
 
76
<p>Next we need to define the render method. Here's where things change a
 
77
bit. Instead of using <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>, We're going to
 
78
use <code class="API"><a href="http://twistedmatrix.com/documents/10.0.0/api/twisted.internet.task.deferLater.html" title="twisted.internet.task.deferLater">deferLater</a></code> this
 
79
time. <code>deferLater</code> accepts a reactor, delay (in seconds, as with
 
80
<code>callLater</code>), and a function to call after the delay to produce that
 
81
elusive object discussed in the description of Deferreds. We're also going to
 
82
use <code>_delayedRender</code> as the callback to add to the
 
83
<code>Deferred</code> returned by <code>deferLater</code>. Since it expects the
 
84
request object as an argument, we're going to set up the <code>deferLater</code>
 
85
call to return a <code>Deferred</code> which has the request object as its
 
86
result.</p>
 
87
 
 
88
<pre class="python"><p class="py-linenumber">1
 
89
2
 
90
</p><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>):
 
91
    <span class="py-src-variable">d</span> = <span class="py-src-variable">deferLater</span>(<span class="py-src-variable">reactor</span>, <span class="py-src-number">5</span>, <span class="py-src-keyword">lambda</span>: <span class="py-src-variable">request</span>)
 
92
</pre>
 
93
 
 
94
<p>The <code>Deferred</code> referenced by <code>d</code> now needs to have the
 
95
<code>_delayedRender</code> callback added to it. Once this is done,
 
96
<code>_delayedRender</code> will be called with the result of <code>d</code>
 
97
(which will be <code>request</code>, of course â€” the result of <code>(lambda:
 
98
request)()</code>).</p>
 
99
 
 
100
<pre class="python"><p class="py-linenumber">1
 
101
</p><span class="py-src-variable">d</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">self</span>.<span class="py-src-variable">_delayedRender</span>)
 
102
</pre>
 
103
 
 
104
<p>Finally, the render method still needs to return <code>NOT_DONE_YET</code>,
 
105
for exactly the same reasons as it did in the previous version of the
 
106
example.</p>
 
107
 
 
108
<pre class="python"><p class="py-linenumber">1
 
109
</p><span class="py-src-keyword">return</span> <span class="py-src-variable">NOT_DONE_YET</span>
 
110
</pre>
 
111
 
 
112
<p>And with that, <code>DelayedResource</code> is now implemented based on a
 
113
<code>Deferred</code>. The example still isn't very realistic, but remember that
 
114
since Deferreds offer a uniform interface to many different asynchronous event
 
115
sources, this code now resembles a real application even more closely; you could
 
116
easily replace <code>deferLater</code> with another
 
117
<code>Deferred</code>-returning API and suddenly you might have a resource that
 
118
does something useful.</p>
 
119
 
 
120
<p>Finally, here's the complete, uninterrupted example source, as an rpy script:</p>
 
121
 
 
122
<pre class="python"><p class="py-linenumber"> 1
 
123
 2
 
124
 3
 
125
 4
 
126
 5
 
127
 6
 
128
 7
 
129
 8
 
130
 9
 
131
10
 
132
11
 
133
12
 
134
13
 
135
14
 
136
15
 
137
16
 
138
</p><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-variable">task</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">deferLater</span>
 
139
<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>
 
140
<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>
 
141
<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>
 
142
 
 
143
<span class="py-src-keyword">class</span> <span class="py-src-identifier">DelayedResource</span>(<span class="py-src-parameter">Resource</span>):
 
144
    <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>):
 
145
        <span class="py-src-variable">request</span>.<span class="py-src-variable">write</span>(<span class="py-src-string">&quot;Sorry to keep you waiting.&quot;</span>)
 
146
        <span class="py-src-variable">request</span>.<span class="py-src-variable">finish</span>()
 
147
 
 
148
    <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>):
 
149
        <span class="py-src-variable">d</span> = <span class="py-src-variable">deferLater</span>(<span class="py-src-variable">reactor</span>, <span class="py-src-number">5</span>, <span class="py-src-keyword">lambda</span>: <span class="py-src-variable">request</span>)
 
150
        <span class="py-src-variable">d</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">self</span>.<span class="py-src-variable">_delayedRender</span>)
 
151
        <span class="py-src-keyword">return</span> <span class="py-src-variable">NOT_DONE_YET</span>
 
152
 
 
153
<span class="py-src-variable">resource</span> = <span class="py-src-variable">DelayedResource</span>()
 
154
</pre>
 
155
 
 
156
</div>
 
157
 
 
158
    <p><a href="../index.html">Index</a></p>
 
159
    <span class="version">Version: 10.0.0</span>
 
160
  </body>
 
161
</html>
 
 
b'\\ No newline at end of file'