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

Side by Side Diff: src/site/docs/dart-up-and-running/ch05.html

Issue 11366023: Updated tech overview (Closed) Base URL: git@github.com:dart-lang/dartlang.org.git@master
Patch Set: Created 8 years, 1 month 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
1 --- 1 ---
2 layout: book 2 layout: book
3 title: "Chapter 5. Walkthrough: Dart Chat" 3 title: "Chapter 5. Walkthrough: Dart Chat"
4 description: "See a real app with both client-side and server-side Dart: Dart Ch at." 4 description: "See a real app with both client-side and server-side Dart: Dart Ch at."
5 has-permalinks: true 5 has-permalinks: true
6 --- 6 ---
7 <h1 id="ch05"> {{ page.title }} </h1> 7 <h1 id="ch05"> {{ page.title }} </h1>
8 8
9 <p>This chapter points out some of the useful and fun features of Dart 9 <p>This chapter points out some of the useful and fun features of Dart
10 that we used to build Dart Chat, a client-server app. If you’d like 10 that we used to build Dart Chat, a client-server app. If you’d like
11 step-by-step instructions on building Dart Chat, you might be interested in 11 step-by-step instructions on building Dart Chat, you might be interested in
12 our <a class="ulink" href="https://www.dartlang.org/slides/2012/06/io12/Bullse ye-Your-first-Dart-app-Codelab-GoogleIO2012.pdf">code 12 our <a class="ulink" href="https://www.dartlang.org/slides/2012/06/io12/Bullse ye-Your-first-Dart-app-Codelab-GoogleIO2012.pdf">code
13 lab</a>.</p><p><a class="xref" href="ch05.html#DartChat-screenshot" title="Fig ure 5-1. Multiple chat clients can use the chat server to talk">Figure 5-1</a> s hows the chat client executing 13 lab</a>.</p><p><a class="xref" href="ch05.html#DartChat-screenshot" title="Fig ure 5-1. Multiple chat clients can use the chat server to talk">Figure 5-1</a> s hows the chat client executing
14 in a Dartium window. Each copy of the chat client can send messages to the 14 in a Dartium window. Each copy of the chat client can send messages to the
15 chat server, which forwards those messages to the other chat clients.</p><div class="figure"id="DartChat-screenshot"/><div class="figure-contents"><div class= "mediaobject"><img src="figs/web/daur_0501.png" alt="Multiple chat clients can u se the chat server to talk"/></div></div><p class="title">Figure 5-1. Multiple c hat clients can use the chat server to talk</p></div><div class="sect1" title="H ow to run Dart Chat"><div class="titlepage"><div><div><h1 class="title"id="ch05- how-to-run"/>How to run Dart Chat</h1></div></div></div><p>The easiest way to ru n the Dart Chat client and server apps is to 15 chat server, which forwards those messages to the other chat clients.</p><div class="figure"id="DartChat-screenshot"/><div class="figure-contents"><div class= "mediaobject"><img src="figs/web/daur_0501.png" alt="Multiple chat clients can u se the chat server to talk"/></div></div><p class="title">Figure 5-1. Multiple c hat clients can use the chat server to talk</p></div><div class="sect1" title="H ow to run Dart Chat"><div class="titlepage"><div><div><h2 class="title"id="ch05- how-to-run"/>How to run Dart Chat</h2></div></div></div><p>The easiest way to ru n the Dart Chat client and server apps is to
16 open them in Dart Editor.</p><div class="orderedlist"><ol class="orderedlist "><li class="listitem"><p>Download the Dart Chat source code from GitHub:</p><p> 16 open them in Dart Editor.</p><div class="orderedlist"><ol class="orderedlist "><li class="listitem"><p>Download the Dart Chat source code from GitHub:</p><p>
17 <a class="ulink" href="https://github.com/dart-lang/io-2012-dart-code- lab">https://github.com/dart-lang/io-2012-dart-code-lab</a> 17 <a class="ulink" href="https://github.com/dart-lang/io-2012-dart-code- lab">https://github.com/dart-lang/io-2012-dart-code-lab</a>
18 </p></li><li class="listitem"><p>In Dart Editor, use <span class="bold"> <strong>File &gt; Open 18 </p></li><li class="listitem"><p>In Dart Editor, use <span class="bold"> <strong>File &gt; Open
19 Folder...</strong></span>, to open the <span class="bold"><strong>finish ed</strong></span> directory of the Dart Chat source 19 Folder...</strong></span>, to open the <span class="bold"><strong>finish ed</strong></span> directory of the Dart Chat source
20 code.</p></li><li class="listitem"><p>Select <code class="literal">chat- server.dart</code>, and then click 20 code.</p></li><li class="listitem"><p>Select <code class="literal">chat- server.dart</code>, and then click
21 the Run button <span class="inlinemediaobject"><img src="figs/incoming/r un.png" alt=""/></span>.</p><p>A view named chat-server appears in Dart Editor, displaying 21 the Run button <span class="inlinemediaobject"><img src="figs/incoming/r un.png" alt=""/></span>.</p><p>A view named chat-server appears in Dart Editor, displaying
22 debugging output for the server.</p></li><li class="listitem"><p>Select <code class="literal">client/chat-client.dart</code>, and then 22 debugging output for the server.</p></li><li class="listitem"><p>Select <code class="literal">client/chat-client.dart</code>, and then
23 click the Run button <span class="inlinemediaobject"><img src="figs/inco ming/run.png" alt=""/></span>.</p><p>Dartium launches, if necessary, and display s a Dart Chat 23 click the Run button <span class="inlinemediaobject"><img src="figs/inco ming/run.png" alt=""/></span>.</p><p>Dartium launches, if necessary, and display s a Dart Chat
24 tab.</p></li><li class="listitem"><p>To create another copy of the chat client, go to the Dart 24 tab.</p></li><li class="listitem"><p>To create another copy of the chat client, go to the Dart
25 Chat tab in Dartium. Right-click the tab, and choose <span class="bold"> <strong>Duplicate</strong></span>.</p></li></ol></div></div><div class="sect1" t itle="How Dart Chat works"><div class="titlepage"><div><div><h1 class="title"id= "ch05-how-it-works"/>How Dart Chat works</h1></div></div></div><p>The chat serve r and client are simple. The chat server is an HTTP 25 Chat tab in Dartium. Right-click the tab, and choose <span class="bold"> <strong>Duplicate</strong></span>.</p></li></ol></div></div><div class="sect1" t itle="How Dart Chat works"><div class="titlepage"><div><div><h2 class="title"id= "ch05-how-it-works"/>How Dart Chat works</h2></div></div></div><p>The chat serve r and client are simple. The chat server is an HTTP
26 server that provides a WebSocket. The chat client uses that WebSocket for 26 server that provides a WebSocket. The chat client uses that WebSocket for
27 a bi-directional communication channel with the server. The client sends 27 a bi-directional communication channel with the server. The client sends
28 chat messages to the sever over the WebSocket, and the server relays those 28 chat messages to the sever over the WebSocket, and the server relays those
29 messages to all other connected clients.</p><p>As <a class="xref" href="ch05 .html#web-socket-connections" title="Figure 5-2. Chat clients connect to a web s ocket created by the chat server">Figure 5-2</a> shows, the server 29 messages to all other connected clients.</p><p>As <a class="xref" href="ch05 .html#web-socket-connections" title="Figure 5-2. Chat clients connect to a web s ocket created by the chat server">Figure 5-2</a> shows, the server
30 starts things off by listening for requests to 30 starts things off by listening for requests to
31 <code class="literal">ws://127.0.0.1:1337/ws</code>. Chat clients then conne ct to 31 <code class="literal">ws://127.0.0.1:1337/ws</code>. Chat clients then conne ct to
32 that URL.</p><div class="figure"id="web-socket-connections"/><div class="fig ure-contents"><div class="mediaobject"><img src="figs/web/daur_0502.png" alt="Ch at clients connect to a web socket created by the chat server"/></div></div><p c lass="title">Figure 5-2. Chat clients connect to a web socket created by the cha t 32 that URL.</p><div class="figure"id="web-socket-connections"/><div class="fig ure-contents"><div class="mediaobject"><img src="figs/web/daur_0502.png" alt="Ch at clients connect to a web socket created by the chat server"/></div></div><p c lass="title">Figure 5-2. Chat clients connect to a web socket created by the cha t
33 server</p></div><p>The real communication between client and server happen s when the 33 server</p></div><p>The real communication between client and server happen s when the
34 user enters a message. As <a class="xref" href="ch05.html#web-socket-message s" title="Figure 5-3. A chat client uses the server to send a message to other c hat clients">Figure 5-3</a> shows, 34 user enters a message. As <a class="xref" href="ch05.html#web-socket-message s" title="Figure 5-3. A chat client uses the server to send a message to other c hat clients">Figure 5-3</a> shows,
35 the chat client sends a JSON-encoded version of the message to the server. 35 the chat client sends a JSON-encoded version of the message to the server.
36 The server then forwards the message to every client except the one that 36 The server then forwards the message to every client except the one that
37 sent it.</p><div class="figure"id="web-socket-messages"/><div class="figure- contents"><div class="mediaobject"><img src="figs/web/daur_0503.png" alt="A chat client uses the server to send a message to other chat clients"/></div></div><p class="title">Figure 5-3. A chat client uses the server to send a message to ot her chat 37 sent it.</p><div class="figure"id="web-socket-messages"/><div class="figure- contents"><div class="mediaobject"><img src="figs/web/daur_0503.png" alt="A chat client uses the server to send a message to other chat clients"/></div></div><p class="title">Figure 5-3. A chat client uses the server to send a message to ot her chat
38 clients</p></div><p>The chat server implements an HTTP server to listen fo r WebSocket 38 clients</p></div><p>The chat server implements an HTTP server to listen fo r WebSocket
39 requests. The HTTP server can also serve static files from the client 39 requests. The HTTP server can also serve static files from the client
40 directory—for example, http://127.0.0.1:1337/chat-log.txt shows the file 40 directory—for example, http://127.0.0.1:1337/chat-log.txt shows the file
41 that’s at client/chat-log.txt.</p><p>The client code is split between HTML ( page structure), CSS (page 41 that’s at client/chat-log.txt.</p><p>The client code is split between HTML ( page structure), CSS (page
42 look), and JavaScript (logic and behavior). That’s typical of web 42 look), and JavaScript (logic and behavior). That’s typical of web
43 clients.</p><p>The twist is that this client’s JavaScript code is produced f rom 43 clients.</p><p>The twist is that this client’s JavaScript code is produced f rom
44 Dart code, thanks to the dart2js compiler. Any modern browser can run this 44 Dart code, thanks to the dart2js compiler. Any modern browser can run this
45 JavaScript code. Dartium (and any other browsers that support Dart) can 45 JavaScript code. Dartium (and any other browsers that support Dart) can
46 run either the JavaScript code or the original Dart code.</p></div><div clas s="sect1" title="The client’s HTML code"><div class="titlepage"><div><div><h1 cl ass="title"id="ch05-client-html-code"/>The client’s HTML code</h1></div></div></ div><p>The main elements in the client UI are two text fields (with the IDs 46 run either the JavaScript code or the original Dart code.</p></div><div clas s="sect1" title="The client’s HTML code"><div class="titlepage"><div><div><h2 cl ass="title"id="ch05-client-html-code"/>The client’s HTML code</h2></div></div></ div><p>The main elements in the client UI are two text fields (with the IDs
47 “chat-username” and “chat-message”) and a status area (ID: 47 “chat-username” and “chat-message”) and a status area (ID:
48 “chat-display”).</p><pre class="programlisting">&lt;!-- In client/index.html : --&gt; 48 “chat-display”).</p><pre class="programlisting">&lt;!-- In client/index.html : --&gt;
49 &lt;textarea id="chat-display" rows="10" disabled&gt;&lt;/textarea&gt; 49 &lt;textarea id="chat-display" rows="10" disabled&gt;&lt;/textarea&gt;
50 ... 50 ...
51 &lt;input id="chat-username" name="chat-username" type="text"&gt; 51 &lt;input id="chat-username" name="chat-username" type="text"&gt;
52 ... 52 ...
53 &lt;input id="chat-message" name="chat-message" type="text" disabled value="ente r message..."&gt;</pre><p>Near the bottom of client/index.html, a couple of &lt; script&gt; 53 &lt;input id="chat-message" name="chat-message" type="text" disabled value="ente r message..."&gt;</pre><p>Near the bottom of client/index.html, a couple of &lt; script&gt;
54 tags tell the browser to execute the client’s Dart or JavaScript 54 tags tell the browser to execute the client’s Dart or JavaScript
55 code:</p><pre class="programlisting">&lt;script type="application/dart" src= "chat-client.dart"&gt;&lt;/script&gt; 55 code:</p><pre class="programlisting">&lt;script type="application/dart" src= "chat-client.dart"&gt;&lt;/script&gt;
56 &lt;script src="dart.js"&gt;&lt;/script&gt;</pre><p>The first line works in brow sers that have an embedded Dart VM and 56 &lt;script src="dart.js"&gt;&lt;/script&gt;</pre><p>The first line works in brow sers that have an embedded Dart VM and
57 so can execute Dart code; currently, only Dartium qualifies. The second 57 so can execute Dart code; currently, only Dartium qualifies. The second
58 line is important for every other browser. It executes dart.js, which is a 58 line is important for every other browser. It executes dart.js, which is a
59 standard script that converts all Dart &lt;script&gt; tags to use 59 standard script that converts all Dart &lt;script&gt; tags to use
60 foo.dart.js instead of foo.dart, with the assumption that foo.dart.js is a 60 foo.dart.js instead of foo.dart, with the assumption that foo.dart.js is a
61 JavaScript version of foo.dart. For non-Dartium browsers, dart.js changes 61 JavaScript version of foo.dart. For non-Dartium browsers, dart.js changes
62 the first &lt;script&gt; tag to the following:</p><pre class="programlisting ">&lt;!-- Inserted by dart.js for non-Dartium browsers --&gt; 62 the first &lt;script&gt; tag to the following:</p><pre class="programlisting ">&lt;!-- Inserted by dart.js for non-Dartium browsers --&gt;
63 &lt;script src="chat-client.dart.js"&gt;&lt;/script&gt;</pre><p>The script conte nts run when the browser has loaded the HTML and 63 &lt;script src="chat-client.dart.js"&gt;&lt;/script&gt;</pre><p>The script conte nts run when the browser has loaded the HTML and
64 constructed its DOM (document object model).</p><p>You can get <a class="uli nk" href="http://dart.googlecode.com/svn/trunk/dart/client/dart.js">dart.js</a> 64 constructed its DOM (document object model).</p><p>You can get <a class="uli nk" href="http://dart.googlecode.com/svn/trunk/dart/client/dart.js">dart.js</a>
65 from the Dart project. See <a class="xref" href="ch04.html#ch04-tools-dart2j s" title="dart2js: The Dart-to-JavaScript compiler">dart2js: The Dart-to-JavaScr ipt compiler</a> for more 65 from the Dart project. See <a class="xref" href="ch04.html#ch04-tools-dart2j s" title="dart2js: The Dart-to-JavaScript compiler">dart2js: The Dart-to-JavaScr ipt compiler</a> for more
66 information about compiling Dart code into its JavaScript 66 information about compiling Dart code into its JavaScript
67 equivalent.</p></div><div class="sect1" title="The client’s Dart code"><div class="titlepage"><div><div><h1 class="title"id="ch05-client-dart-code"/>The cli ent’s Dart code</h1></div></div></div><p>Dart code (client/chat-client.dart) pro vides the client’s logic, 67 equivalent.</p></div><div class="sect1" title="The client’s Dart code"><div class="titlepage"><div><div><h2 class="title"id="ch05-client-dart-code"/>The cli ent’s Dart code</h2></div></div></div><p>Dart code (client/chat-client.dart) pro vides the client’s logic,
68 using the DOM to interact with UI elements. For example, the client’s Dart 68 using the DOM to interact with UI elements. For example, the client’s Dart
69 code uses the DOM to find the text area where the client displays 69 code uses the DOM to find the text area where the client displays
70 messages.</p><div class="sect2" title="Finding DOM elements"><div class="tit lepage"><div><div><h2 class="title"id="id641182"/>Finding DOM elements</h2></div ></div></div><p>The client app uses dart:html’s top-level query() method to get 70 messages.</p><div class="sect2" title="Finding DOM elements"><div class="tit lepage"><div><div><h3 class="title"id="id641182"/>Finding DOM elements</h3></div ></div></div><p>The client app uses dart:html’s top-level query() method to get
71 the client’s UI elements from the DOM.</p><pre class="programlisting">// I n client/chat-client.dart: 71 the client’s UI elements from the DOM.</p><pre class="programlisting">// I n client/chat-client.dart:
72 import 'dart:html'; 72 import 'dart:html';
73 //... 73 //...
74 TextAreaElement chatElem = query('#chat-display'); 74 TextAreaElement chatElem = query('#chat-display');
75 InputElement usernameElem = query('#chat-username'); 75 InputElement usernameElem = query('#chat-username');
76 InputElement messageElem = query('#chat-message');</pre><p>The query() method us es a selector string that identifies an 76 InputElement messageElem = query('#chat-message');</pre><p>The query() method us es a selector string that identifies an
77 element in the DOM. See <a class="xref" href="ch03.html#ch03-finding-eleme nts" title="Finding elements">Finding elements</a> for 77 element in the DOM. See <a class="xref" href="ch03.html#ch03-finding-eleme nts" title="Finding elements">Finding elements</a> for
78 more about selectors.</p></div><div class="sect2" title="Wrapping DOM elem ents"><div class="titlepage"><div><div><h2 class="title"id="id641208"/>Wrapping DOM elements</h2></div></div></div><p>Rather than always dealing with DOM APIs, the chat client wraps 78 more about selectors.</p></div><div class="sect2" title="Wrapping DOM elem ents"><div class="titlepage"><div><div><h3 class="title"id="id641208"/>Wrapping DOM elements</h3></div></div></div><p>Rather than always dealing with DOM APIs, the chat client wraps
79 the elements in Dart objects:</p><pre class="programlisting">chatWindow = new ChatWindow(chatElem); 79 the elements in Dart objects:</p><pre class="programlisting">chatWindow = new ChatWindow(chatElem);
80 usernameInput = new UsernameInput(usernameElem); 80 usernameInput = new UsernameInput(usernameElem);
81 messageInput = new MessageInput(messageElem);</pre><p>ChatWindow, UsernameInput, and MessageInput are custom classes 81 messageInput = new MessageInput(messageElem);</pre><p>ChatWindow, UsernameInput, and MessageInput are custom classes
82 that extend another custom class called View. These Views effectively 82 that extend another custom class called View. These Views effectively
83 separate the DOM manipulation from the application logic.</p><p>Because Da rt has real classes and inheritance, it’s simple to 83 separate the DOM manipulation from the application logic.</p><p>Because Da rt has real classes and inheritance, it’s simple to
84 express the relationship that ChatWindow is-a View. Here’s the complete 84 express the relationship that ChatWindow is-a View. Here’s the complete
85 code for UsernameInput:</p><pre class="programlisting">class UsernameInput extends View&lt;InputElement&gt; { 85 code for UsernameInput:</p><pre class="programlisting">class UsernameInput extends View&lt;InputElement&gt; {
86 UsernameInput(InputElement elem) : super(elem); 86 UsernameInput(InputElement elem) : super(elem);
87 87
88 bind() { // Called by the View constructor. 88 bind() { // Called by the View constructor.
(...skipping 11 matching lines...) Expand all
100 String get username =&gt; elem.value; 100 String get username =&gt; elem.value;
101 }</pre><p>To get the string that’s in the chat-username field, the client 101 }</pre><p>To get the string that’s in the chat-username field, the client
102 app uses the <code class="literal">username</code> getter of a UsernameInp ut 102 app uses the <code class="literal">username</code> getter of a UsernameInp ut
103 object. For example:</p><pre class="programlisting">chatWindow.displayMess age(message, usernameInput.username);</pre><p>Notice how the code uses generics (View&lt;InputElement&gt;) to 103 object. For example:</p><pre class="programlisting">chatWindow.displayMess age(message, usernameInput.username);</pre><p>Notice how the code uses generics (View&lt;InputElement&gt;) to
104 specify what kind of element the View class can encapsulate. In the 104 specify what kind of element the View class can encapsulate. In the
105 preceding example, the UsernameInput wraps an <a class="ulink" href="http: //api.dartlang.org/dart_html/InputElement.html">InputElement.</a> 105 preceding example, the UsernameInput wraps an <a class="ulink" href="http: //api.dartlang.org/dart_html/InputElement.html">InputElement.</a>
106 Expressing this gives tools information that they can use to identify 106 Expressing this gives tools information that they can use to identify
107 bugs or improve code completion.</p><p>Wrapping elements is a technique yo u can use as you develop a 107 bugs or improve code completion.</p><p>Wrapping elements is a technique yo u can use as you develop a
108 simple app that might evolve into a larger app. As the app grows, you 108 simple app that might evolve into a larger app. As the app grows, you
109 might change it to use a real <a class="ulink" href="http://en.wikipedia.o rg/wiki/Model-view-controller">model-view-controller 109 might change it to use a real <a class="ulink" href="http://en.wikipedia.o rg/wiki/Model-view-controller">model-view-controller
110 (MVC) architecture.</a></p><div class="note" title="Note"><h3 class="title ">Note</h3><p>We expect the Dart project to provide an MVC-type framework for 110 (MVC) architecture.</a></p><div class="note" title="Note"><h4 class="title ">Note</h4><p>We expect the Dart project to provide an MVC-type framework for
111 clients.</p></div></div><div class="sect2" title="Updating DOM elements" ><div class="titlepage"><div><div><h2 class="title"id="id641289"/>Updating DOM e lements</h2></div></div></div><p>The bind() method sets up the event handlers, w hich bind events 111 clients.</p></div></div><div class="sect2" title="Updating DOM elements" ><div class="titlepage"><div><div><h3 class="title"id="id641289"/>Updating DOM e lements</h3></div></div></div><p>The bind() method sets up the event handlers, w hich bind events
112 from the DOM to logic in the Dart objects. For example, in 112 from the DOM to logic in the Dart objects. For example, in
113 UsernameInput, the _onUsernameChange() method is called any time the 113 UsernameInput, the _onUsernameChange() method is called any time the
114 text in the input element changes.</p><p>To display messages in the chat w indow, the ChatWindow class adds 114 text in the input element changes.</p><p>To display messages in the chat w indow, the ChatWindow class adds
115 the message to the text node of the text area.</p><pre class="programlisti ng">class ChatWindow extends View&lt;TextAreaElement&gt; { 115 the message to the text node of the text area.</p><pre class="programlisti ng">class ChatWindow extends View&lt;TextAreaElement&gt; {
116 ChatWindow(TextAreaElement elem) : super(elem); 116 ChatWindow(TextAreaElement elem) : super(elem);
117 117
118 displayMessage(String msg, String from) { 118 displayMessage(String msg, String from) {
119 _display('$from: $msg\n'); 119 _display('$from: $msg\n');
120 } 120 }
121 121
122 displayNotice(String notice) { 122 displayNotice(String notice) {
123 _display('[system]: $notice\n'); 123 _display('[system]: $notice\n');
124 } 124 }
125 125
126 _display(String str) { 126 _display(String str) {
127 elem.addText(str); 127 elem.addText(str);
128 } 128 }
129 }</pre><p>In both examples, the View objects expose an application-specific 129 }</pre><p>In both examples, the View objects expose an application-specific
130 API—for example, displayMessage() or _onUsernameChange()—and encapsulate 130 API—for example, displayMessage() or _onUsernameChange()—and encapsulate
131 the manipulation of DOM elements.</p></div><div class="sect2" title="Encod ing and decoding messages"><div class="titlepage"><div><div><h2 class="title"id= "ch05-dart-json"/>Encoding and decoding messages</h2></div></div></div><p>The da rt:json library encodes and decodes JSON-formatted messages. 131 the manipulation of DOM elements.</p></div><div class="sect2" title="Encod ing and decoding messages"><div class="titlepage"><div><div><h3 class="title"id= "ch05-dart-json"/>Encoding and decoding messages</h3></div></div></div><p>The da rt:json library encodes and decodes JSON-formatted messages.
132 JSON is an easy way to provide string message data to WebSockets. Using 132 JSON is an easy way to provide string message data to WebSockets. Using
133 JSON also gives a bit of structure to the messages and leaves the door 133 JSON also gives a bit of structure to the messages and leaves the door
134 open to creating more detailed messages in the future.</p><p>The stringify () method converts a Dart object to a JSON encoded 134 open to creating more detailed messages in the future.</p><p>The stringify () method converts a Dart object to a JSON encoded
135 string, and the parse() method converts a JSON string back into a Dart 135 string, and the parse() method converts a JSON string back into a Dart
136 object. Here’s the JSON-related code from the chat client:</p><pre class=" programlisting">import 'dart:json'; 136 object. Here’s the JSON-related code from the chat client:</p><pre class=" programlisting">import 'dart:json';
137 137
138 var encoded = JSON.stringify({'f': from, 'm': message}); 138 var encoded = JSON.stringify({'f': from, 'm': message});
139 Map message = JSON.parse(encodedMessage);</pre><p>See <a class="xref" href="ch03 .html#ch03-json" title="dart:json - Encoding and decoding objects">dart:json - E ncoding and decoding objects</a> for more information.</p></div><div class="sect 2" title="Communicating with WebSockets"><div class="titlepage"><div><div><h2 cl ass="title"id="id641357"/>Communicating with WebSockets</h2></div></div></div><p >The custom class ChatConnection takes care of the chat client’s 139 Map message = JSON.parse(encodedMessage);</pre><p>See <a class="xref" href="ch03 .html#ch03-json" title="dart:json - Encoding and decoding objects">dart:json - E ncoding and decoding objects</a> for more information.</p></div><div class="sect 2" title="Communicating with WebSockets"><div class="titlepage"><div><div><h3 cl ass="title"id="id641357"/>Communicating with WebSockets</h3></div></div></div><p >The custom class ChatConnection takes care of the chat client’s
140 WebSocket communication. First it connects to the WebSocket by calling 140 WebSocket communication. First it connects to the WebSocket by calling
141 the WebSocket constructor with the argument 141 the WebSocket constructor with the argument
142 <code class="literal">'ws://127.0.0.1:1337/ws'</code>. Then ChatConnection adds 142 <code class="literal">'ws://127.0.0.1:1337/ws'</code>. Then ChatConnection adds
143 event handlers for open, close, error, and message events, using the 143 event handlers for open, close, error, and message events, using the
144 WebSocketEvents object it gets from webSocket.on. For example, here’s 144 WebSocketEvents object it gets from webSocket.on. For example, here’s
145 the code that responds to message events:</p><pre class="programlisting">w ebSocket.on.message.add((MessageEvent e) { 145 the code that responds to message events:</p><pre class="programlisting">w ebSocket.on.message.add((MessageEvent e) {
146 print('received message ${e.data}'); 146 print('received message ${e.data}');
147 _receivedEncodedMessage(e.data); 147 _receivedEncodedMessage(e.data);
148 });</pre><p>The _receivedEncodedMessage() method just parses the JSON data and 148 });</pre><p>The _receivedEncodedMessage() method just parses the JSON data and
149 displays it in the status area.</p><pre class="programlisting">_receivedEn codedMessage(String encodedMessage) { 149 displays it in the status area.</p><pre class="programlisting">_receivedEn codedMessage(String encodedMessage) {
(...skipping 29 matching lines...) Expand all
179 if (!encounteredError) { 179 if (!encounteredError) {
180 window.setTimeout(() =&gt; _init(retrySeconds*2), 1000*retrySeconds); 180 window.setTimeout(() =&gt; _init(retrySeconds*2), 1000*retrySeconds);
181 } 181 }
182 encounteredError = true; 182 encounteredError = true;
183 } 183 }
184 184
185 //... 185 //...
186 186
187 webSocket.on.close.add((e) =&gt; scheduleReconnect()); 187 webSocket.on.close.add((e) =&gt; scheduleReconnect());
188 webSocket.on.error.add((e) =&gt; scheduleReconnect());</pre><p>The reconnect l ogic uses setTimeout() to schedule a retry using an 188 webSocket.on.error.add((e) =&gt; scheduleReconnect());</pre><p>The reconnect l ogic uses setTimeout() to schedule a retry using an
189 exponential backoff algorithm.</p></div></div><div class="sect1" title="Th e server’s code"><div class="titlepage"><div><div><h1 class="title"id="ch05-serv er"/>The server’s code</h1></div></div></div><p>The chat-server.dart file contai ns most of the code used in the chat 189 exponential backoff algorithm.</p></div></div><div class="sect1" title="Th e server’s code"><div class="titlepage"><div><div><h2 class="title"id="ch05-serv er"/>The server’s code</h2></div></div></div><p>The chat-server.dart file contai ns most of the code used in the chat
190 server. It is responsible for serving static files and managing WebSocket 190 server. It is responsible for serving static files and managing WebSocket
191 connections. The chat server also logs the chat messages to a file.</p><div class="sect2" title="Serving static files"><div class="titlepage"><div><div><h2 class="title"id="id641449"/>Serving static files</h2></div></div></div><p>The ch at server uses dart:io’s HttpServer to implement a web 191 connections. The chat server also logs the chat messages to a file.</p><div class="sect2" title="Serving static files"><div class="titlepage"><div><div><h3 class="title"id="id641449"/>Serving static files</h3></div></div></div><p>The ch at server uses dart:io’s HttpServer to implement a web
192 server. The default request handler is configured to serve static files 192 server. The default request handler is configured to serve static files
193 from a specific directory on the file system.</p><pre class="programlistin g">runServer(String basePath, int port) { 193 from a specific directory on the file system.</p><pre class="programlistin g">runServer(String basePath, int port) {
194 HttpServer server = new HttpServer(); 194 HttpServer server = new HttpServer();
195 server.defaultRequestHandler = new StaticFileHandler(basePath).onRequest; 195 server.defaultRequestHandler = new StaticFileHandler(basePath).onRequest;
196 //... 196 //...
197 server.onError = (error) =&gt; print(error); 197 server.onError = (error) =&gt; print(error);
198 server.listen('127.0.0.1', 1337); 198 server.listen('127.0.0.1', 1337);
199 print('listening for connections on $port'); 199 print('listening for connections on $port');
200 } 200 }
201 201
(...skipping 13 matching lines...) Expand all
215 onRequest(HttpRequest request, HttpResponse response) { 215 onRequest(HttpRequest request, HttpResponse response) {
216 //... 216 //...
217 file.exists().then((found) { 217 file.exists().then((found) {
218 if (found) { 218 if (found) {
219 // ...Respond with the file’s contents... 219 // ...Respond with the file’s contents...
220 } else { 220 } else {
221 // ...Send a 404 response... 221 // ...Send a 404 response...
222 } 222 }
223 });</pre><p>See <a class="xref" href="ch03.html#ch03-asynchronous-programming" title="Asynchronous programming">Asynchronous programming</a> for more 223 });</pre><p>See <a class="xref" href="ch03.html#ch03-asynchronous-programming" title="Asynchronous programming">Asynchronous programming</a> for more
224 information about using Future, and <a class="xref" href="ch03.html#ch03-f iles-and-directories" title="Files and directories">Files and directories</a> fo r details on file and 224 information about using Future, and <a class="xref" href="ch03.html#ch03-f iles-and-directories" title="Files and directories">Files and directories</a> fo r details on file and
225 directory I/O.</p></div><div class="sect2" title="Managing WebSocket conne ctions"><div class="titlepage"><div><div><h2 class="title"id="id641516"/>Managin g WebSocket connections</h2></div></div></div><p>In addition to serving static f iles, the chat server manages 225 directory I/O.</p></div><div class="sect2" title="Managing WebSocket conne ctions"><div class="titlepage"><div><div><h3 class="title"id="id641516"/>Managin g WebSocket connections</h3></div></div></div><p>In addition to serving static f iles, the chat server manages
226 WebSocket connections, routing chat messages between clients. The 226 WebSocket connections, routing chat messages between clients. The
227 dart:io WebSocketHandler class accepts HTTP connections, converts them 227 dart:io WebSocketHandler class accepts HTTP connections, converts them
228 into WebSocket connections, and then passes them to ChatHandler.</p><pre c lass="programlisting">runServer(String basePath, int port) { 228 into WebSocket connections, and then passes them to ChatHandler.</p><pre c lass="programlisting">runServer(String basePath, int port) {
229 //... 229 //...
230 WebSocketHandler wsHandler = new WebSocketHandler(); 230 WebSocketHandler wsHandler = new WebSocketHandler();
231 wsHandler.onOpen = new ChatHandler(basePath).onOpen; 231 wsHandler.onOpen = new ChatHandler(basePath).onOpen;
232 }</pre><p>ChatHandler is a custom class that takes care of all WebSocket 232 }</pre><p>ChatHandler is a custom class that takes care of all WebSocket
233 communication for the chat server. Here is its implementation.</p><pre cla ss="programlisting">class ChatHandler { 233 communication for the chat server. Here is its implementation.</p><pre cla ss="programlisting">class ChatHandler {
234 Set&lt;WebSocketConnection&gt; connections; 234 Set&lt;WebSocketConnection&gt; connections;
235 //... 235 //...
(...skipping 14 matching lines...) Expand all
250 }; 250 };
251 251
252 conn.onError = (e) { 252 conn.onError = (e) {
253 connections.remove(conn); 253 connections.remove(conn);
254 }; 254 };
255 } 255 }
256 }</pre><p>When a client connects, the server adds the client’s WebSocket 256 }</pre><p>When a client connects, the server adds the client’s WebSocket
257 connection to a collection. When the client disconnects (either through 257 connection to a collection. When the client disconnects (either through
258 an error or on purpose), the server removes that client’s connection 258 an error or on purpose), the server removes that client’s connection
259 from the collection. When a new message arrives, the server sends the 259 from the collection. When a new message arrives, the server sends the
260 message to all connected clients except the original source.</p></div><div class="sect2" title="Logging messages to a file"><div class="titlepage"><div><d iv><h2 class="title"id="id641560"/>Logging messages to a file</h2></div></div></ div><p>The chat server logs data to a file, client/chat-log.txt, using a 260 message to all connected clients except the original source.</p></div><div class="sect2" title="Logging messages to a file"><div class="titlepage"><div><d iv><h3 class="title"id="id641560"/>Logging messages to a file</h3></div></div></ div><p>The chat server logs data to a file, client/chat-log.txt, using a
261 custom library implemented in file-logger.dart. This library uses an 261 custom library implemented in file-logger.dart. This library uses an
262 isolate to handle file I/O without tying up the root isolate. Here’s the 262 isolate to handle file I/O without tying up the root isolate. Here’s the
263 code that creates and starts this isolate:</p><pre class="programlisting"> SendPort _loggingPort = spawnFunction(startLogging);</pre><p>The value returned by dart:isolate’s spawnFunction() is a SendPort 263 code that creates and starts this isolate:</p><pre class="programlisting"> SendPort _loggingPort = spawnFunction(startLogging);</pre><p>The value returned by dart:isolate’s spawnFunction() is a SendPort
264 object. Because isolates share no data, messages sent to ports are the 264 object. Because isolates share no data, messages sent to ports are the
265 only way for the root isolate to communicate with the spawned 265 only way for the root isolate to communicate with the spawned
266 isolate.</p><p>The argument to spawnFunction() points to the startLogging( ) 266 isolate.</p><p>The argument to spawnFunction() points to the startLogging( )
267 function, which implements the logging isolate. The logic for the 267 function, which implements the logging isolate. The logic for the
268 logging isolate is simple: the first message specifies the log file 268 logging isolate is simple: the first message specifies the log file
269 location, and subsequent messages provide data to write to the log 269 location, and subsequent messages provide data to write to the log
270 file.</p><pre class="programlisting">startLogging() { 270 file.</p><pre class="programlisting">startLogging() {
(...skipping 14 matching lines...) Expand all
285 }</pre><p>In the preceding code, the port property used by startLogging() 285 }</pre><p>In the preceding code, the port property used by startLogging()
286 refers to a ReceivePort provided by dart:isolate. The port is how this 286 refers to a ReceivePort provided by dart:isolate. The port is how this
287 isolate gets data from the root isolate. If this isolate needed to send 287 isolate gets data from the root isolate. If this isolate needed to send
288 messages back to the root isolate, it could use the replyTo argument (a 288 messages back to the root isolate, it could use the replyTo argument (a
289 SendPort) to do so.</p><p>Recall that in the root isolate, the _loggingPor t variable holds a 289 SendPort) to do so.</p><p>Recall that in the root isolate, the _loggingPor t variable holds a
290 SendPort that the root isolate uses to send messages to the logging 290 SendPort that the root isolate uses to send messages to the logging
291 isolate. Every time the chat server calls the log() method, the root 291 isolate. Every time the chat server calls the log() method, the root
292 isolate sends the log data:</p><pre class="programlisting">void log(String message) { 292 isolate sends the log data:</p><pre class="programlisting">void log(String message) {
293 _loggingPort.send(message); 293 _loggingPort.send(message);
294 }</pre><p>See <a class="xref" href="ch03.html#ch03-dartisolate---concurrency-wit h-isolates" title="dart:isolate - Concurrency with isolates">dart:isolate - Conc urrency with isolates</a> for more 294 }</pre><p>See <a class="xref" href="ch03.html#ch03-dartisolate---concurrency-wit h-isolates" title="dart:isolate - Concurrency with isolates">dart:isolate - Conc urrency with isolates</a> for more
295 information about using isolates.</p></div></div><div class="sect1" title= "What next?"><div class="titlepage"><div><div><h1 class="title"id="ch05-what-nex t"/>What next?</h1></div></div></div><p>You’ve seen how the Dart Chat sample use s both server-side and 295 information about using isolates.</p></div></div><div class="sect1" title= "What next?"><div class="titlepage"><div><div><h2 class="title"id="ch05-what-nex t"/>What next?</h2></div></div></div><p>You’ve seen how the Dart Chat sample use s both server-side and
296 client-side Dart code to implement a web app. Here are some other samples 296 client-side Dart code to implement a web app. Here are some other samples
297 you might want to look at:</p><div class="itemizedlist"><ul class="itemizedl ist"><li class="listitem"><p><a class="ulink" href="https://code.google.com/p/da rt/source/browse/#svn%2Ftrunk%2Fdart%2Fsamples%2Fsolar"> 297 you might want to look at:</p><div class="itemizedlist"><ul class="itemizedl ist"><li class="listitem"><p><a class="ulink" href="https://code.google.com/p/da rt/source/browse/#svn%2Ftrunk%2Fdart%2Fsamples%2Fsolar">
298 Solar,</a> which simulates the solar system with animations in a 298 Solar,</a> which simulates the solar system with animations in a
299 canvas, using requestAnimationFrame().</p></li><li class="listitem"><p>< a class="ulink" href="https://code.google.com/p/dart/source/browse/#svn%2Ftrunk% 2Fdart%2Fsamples%2Fspirodraw"> 299 canvas, using requestAnimationFrame().</p></li><li class="listitem"><p>< a class="ulink" href="https://code.google.com/p/dart/source/browse/#svn%2Ftrunk% 2Fdart%2Fsamples%2Fspirodraw">
300 Spirodraw,</a> a fun, interactive tool to build colorful works of 300 Spirodraw,</a> a fun, interactive tool to build colorful works of
301 art.</p></li></ul></div><p>Finally, please visit our website and join th e discussion. We look 301 art.</p></li></ul></div><p>Finally, please visit our website and join th e discussion. We look
302 forward to hearing from you!</p><div class="itemizedlist"><ul class="itemize dlist"><li class="listitem"><p> 302 forward to hearing from you!</p><div class="itemizedlist"><ul class="itemize dlist"><li class="listitem"><p>
303 <a class="ulink" href="http://www.dartlang.org">Dart 303 <a class="ulink" href="http://www.dartlang.org">Dart
304 website</a> 304 website</a>
305 </p></li><li class="listitem"><p> 305 </p></li><li class="listitem"><p>
306 <a class="ulink" href="http://www.dartlang.org/mailing-list"> Dart 306 <a class="ulink" href="http://www.dartlang.org/mailing-list"> Dart
307 discussion group</a> 307 discussion group</a>
308 </p></li><li class="listitem"><p> 308 </p></li><li class="listitem"><p>
309 <a class="ulink" href="http://stackoverflow.com/tags/dart"> Dart 309 <a class="ulink" href="http://stackoverflow.com/tags/dart"> Dart
310 questions on Stack Overflow</a> 310 questions on Stack Overflow</a>
311 </p></li></ul> 311 </p></li></ul>
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698