Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(87)

Side by Side Diff: src/site/articles/using-future-based-apis/index.markdown

Issue 99503002: appropriating Shailen's excellent Futures intro into tutorial (Closed) Base URL: https://github.com/dart-lang/dartlang.org.git@master
Patch Set: another pesky file Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 ---
2 layout: article
3 title: "Using Future Based APIs"
4 description: "A first look at Futures and how to use them to make your
5 asynchronous code better."
6 rel:
7 author: shailen-tuli
8 has-permalinks: true
9 article:
10 written_on: 2013-02-07
11 collection: libraries-and-apis
12 ---
13
14 {% include toc.html %}
15
16 # {{ page.title }}
17
18 _Written by Shailen Tuli, February 2013_
19
20 ## Introduction
21
22 Dart is a single-threaded programming language. If any code blocks the thread
23 of execution, the program effectively freezes. Let's look at some code where
24 this happens:
25
26 {% prettify dart %}
27 import 'dart:io';
28
29 void printDailyNewsDigest() {
30 File file = new File("dailyNewsDigest.txt");
31 print(file.readAsStringSync());
32 }
33
34 void main() {
35 printDailyNewsDigest();
36 printWinningLotteryNumbers();
37 printWeatherForecast();
38 printBaseballScore();
39 }
40 {% endprettify %}
41
42 Our program reads the news of the day from a file, `dailyNewsDigest.txt`,
43 prints it, and then prints a bunch of other items of interest to the user:
44
45 <Contents of dailyNewsDigest.txt>
46 Winning lotto numbers: [23, 63, 87, 26, 2]
47 Tomorrow's forecast: 70F, sunny.
48 Baseball score: Red Sox 10, Yankees 0
49
50 Our code is problematic: since `readAsStringSync()` blocks, the remaining code
51 runs only when `readAsStringSync()` returns with the contents of the file,
52 _however long that takes_. And if reading the file takes a long time, the
53 user waits passively, wondering if she won the lottery, what tomorrow's weather
54 will be like, and who won today's game. Not good.
55
56 To help keep the application responsive, Dart library authors use an
57 asynchronous model when defining functions that do potentially expensive work.
58 Such functions return their value using a Future.
59
60 ## What is a Future?
61
62 A Future represents a means for getting a value sometime in the future. When a
63 function that returns a Future is invoked, two things happen:
64
65 1. The function queues up work to be done and returns an uncompleted Future
66 object immediately.
67 1. Later, when a value is available, the Future object completes with that
68 value (or with an error; we'll discuss that later).
69
70 To get the value that the Future represents, use the `then()` method to
71 register a callback. This callback fires when the Future completes.
72
73 ## Using a Future
74
75 Let's rewrite `printDailyNewsDigest()` to get the file contents
76 asynchronously:
77
78 {% prettify dart %}
79 import 'dart:io';
80 import 'dart:async';
81
82 void printDailyNewsDigest() {
83 File file = new File("dailyNewsDigest.txt");
84 Future future = file.readAsString();
85 future.then((content) {
86 print(content);
87 });
88 }
89 {% endprettify %}
90
91 The `printDailyNewsDigest()` function now uses `readAsString()`, which is
92 non-blocking. Calling `readAsString()` queues up the work to be done but
93 doesn't stop the rest of the code from executing. The program prints the
94 lottery numbers, the forecast, and the baseball score; when
95 `readAsString()` finishes reading the news file, the program prints its
96 contents. If `readAsString()` takes a little while to complete its work, no
97 great harm is done: the user gets to read other things before the daily news
98 digest is printed.
99
100 Winning lotto numbers: [23, 63, 87, 26, 2]
101 Tomorrow's forecast: 70F, sunny.
102 Baseball score: Red Sox 10, Yankees 0
103 <Contents of dailyNewsDigest.txt>
104
105 ## Sequence of events during code execution
106
107 The preceding code executes in three steps:
108
109 1. The program enters `main()`, which calls `printDailyNewsDigest()`, which
110 queues up the file reading task. After calling the remaining print functions,
111 `main()` exits, but the program continues.
112 1. The work scheduled by `readAsString()` is performed, and the contents of the
113 file are read into memory. When the entire file is read, the Future completes
114 with the file contents.
115 1. The callback registered within `then()` fires and prints the contents
116 of the news file.
117
118 Calling `then()` returns a new Future, which completes with the value
119 returned by `then()`'s callback. This means that calls to `then()` can be
120 chained (we'll see examples of this later).
121
122 ## Handling errors when dealing with Futures
123
124 If a Future-returning function completes with an error, the Future returned by
125 `then()` also completes with an error. We can capture that error using
126 `catchError()`:
127
128 {% prettify dart %}
129
130 void printDailyNewsDigest() {
131 File file = new File("dailyNewsDigest.txt");
132 Future future = file.readAsString();
133 future.then((content) => doSomethingWith(content))
134 .catchError((e) => handleError(e));
135 }
136 {% endprettify %}
137
138 If `dailyNewsDigest.txt` doesn't exist or isn't available for reading,
139 the code above executes as follows:
140
141 1. `readAsString()`'s Future completes with an error.
142 1. `then()`'s Future completes with an error.
143 1. `catchError()`'s callback handles the error, `catchError()`'s Future
144 completes normally, and the error does not propagate.
145
146 <aside class="alert alert-info" markdown="1">
147 Chaining catchError() to then() is a common pattern when working with
148 functions that return Futures.
149 <strong>
150 Consider this pairing the asynchronous equivalent of try-catch blocks.
151 </strong>
152 </aside>
153
154 Like `then()`, `catchError()` returns a new Future that completes with
155 the return value of its callback.
156
157 For more details and examples, read
158 [Futures and Error Handling](/articles/futures-and-error-handling/).
159
160
161 ## Calling multiple functions that return Futures
162
163 Consider three functions, `expensiveA()`, `expensiveB()`, and `expensiveC()`,
164 that return Futures. You can invoke them sequentially (one function starts
165 when a previous one completes), or you can kick off all of them at the same
166 time and do something once all the values return. The Future interface
167 is fluid enough to deal with both use cases.
168
169 ### Chaining function calls using then()
170
171 When Future-returning functions need to run in order, use
172 chained `then()` calls:
173
174 {% prettify dart %}
175 expensiveA().then((aValue) => expensiveB())
176 .then((bValue) => expensiveC())
177 .then((cValue) => doSomethingWith(cValue));
178 {% endprettify %}
179
180 Nested callbacks also work, but they're harder to read and not as Dart-y.
181
182 ### Waiting on multiple Futures to complete using Future.wait()
183
184 If the order of execution of the functions is not important,
185 you can use `Future.wait()` to handle multiple Future objects
186 without having to explicitly chain function calls.
187
188 The functions get triggered in quick succession; when all of them
189 complete with a value, `Future.wait()` returns a new Future.
190 This Future completes with a list containing the values produced by
191 each function.
192
193 {% prettify dart %}
194 Future.wait([expensiveA(), expensiveB(), expensiveC()])
195 .then((List responses) => chooseBestResponse(responses))
196 .catchError((e) => handleError(e));
197 {% endprettify %}
198
199 If any of the invoked functions completes with an error, the Future returned
200 by `Future.wait()` also completes with an error. Use `catchError()` to handle
201 the error.
202
203 ## More information
204
205 Read the following documentation for more details on using Futures:
206
207 * [Futures and Error Handling](/articles/futures-and-error-handling/),
208 an article that starts where this one ends
209 * [The Event Loop and Dart](/articles/event-loop/),
210 an article that describes how to schedule tasks using Futures
211 * [Future API reference](http://api.dartlang.org/dart_async/Future.html)
212
OLDNEW
« no previous file with comments | « src/site/articles/using-future-based-apis/code/example5.dart ('k') | src/site/docs/tutorials/fetchdata/index.markdown » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698