<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom">

 <title>sitr.us</title>
 
 <link href="http://sitr.us/" />
 <updated>2013-05-22T18:05:12-07:00</updated>
 <id>http://sitr.us/</id>
 <author>
   <name>Jesse Hallett</name>
   <email>jesse@sitr.us</email>
 </author>

 
 
 <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/hallettj" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="hallettj" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry>
   <title>Functional Reactive Programming in JavaScript</title>
   <link href="http://sitr.us/2013/05/22/functional-reactive-programming-in-javascript.html" />
   <updated>2013-05-22T00:00:00-07:00</updated>
   <id>http://sitr.us/2013/05/22/functional-reactive-programming-in-javascript</id>
   <content type="html">&lt;p&gt;I had a great time at &lt;a href='http://nodepdx.org/'&gt;NodePDX&lt;/a&gt; last week. There were many talks packed into a short span of time and I saw many exciting ideas presented. One topic that seemed particularly useful to me was &lt;a href='http://lanyrd.com/2013/nodepdx/schbpc/'&gt;Chris Meiklejohn&amp;#8217;s talk on Functional Reactive Programming (FRP)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I have talked and written about how useful promises are. See &lt;a href='http://sitr.us/2012/07/31/promise-pipelines-in-javascript.html'&gt;Promise Pipelines in JavaScript&lt;/a&gt;. Promises are useful when you want to represent the outcome of an action or a value that will be available at some future time. FRP is similar except that it deals with streams of reoccurring events and dynamic values.&lt;/p&gt;

&lt;p&gt;Here is an example of using FRP to subscribe to changes to a text input. This creates an event stream that could be used for a typeahead search feature:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;inputs&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;#search&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;asEventStream&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;keyup change&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;map&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;event&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;event&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;target&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;value&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt; &lt;span class='p'&gt;})&lt;/span&gt;
    &lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;filter&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;value&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;value&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;length&lt;/span&gt; &lt;span class='o'&gt;&amp;gt;&lt;/span&gt; &lt;span class='mi'&gt;2&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt; &lt;span class='p'&gt;});&lt;/span&gt;

&lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;throttled&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;inputs&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;throttle&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='mi'&gt;500&lt;/span&gt; &lt;span class='cm'&gt;/* ms */&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;

&lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;distinct&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;throttled&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;skipDuplicates&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This creates an event stream from all &lt;code&gt;keyup&lt;/code&gt; and &lt;code&gt;change&lt;/code&gt; events on the given input. The stream is transformed into a stream of strings matching the value of the input when each event occurs. Then that stream is filtered so that subscribers to &lt;code&gt;inputs&lt;/code&gt; will only receive events if the value of the input has a length greater than two.&lt;/p&gt;

&lt;p&gt;Streams can be assigned to variables, shared, and used as inputs to create more specific streams. In the example above &lt;code&gt;inputs&lt;/code&gt; is used to create two more streams: one that limits the stream so that events are emitted at most every 500 ms and another that takes the throttled stream and drops duplicate values that appear consecutively. So when the final stream, &lt;code&gt;distinct&lt;/code&gt;, is consumed later it is guaranteed that events 1) will be non-empty strings with length greater than two, 2) will not occur too frequently, and 3) will not include duplicates.&lt;/p&gt;

&lt;p&gt;That stream can be fed through a service via ajax calls to show a live list of results:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;span class='kd'&gt;function&lt;/span&gt; &lt;span class='nx'&gt;searchWikipedia&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;term&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;url&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;//en.wikipedia.org/w/api.php?callback=?&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
    &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;getJSON&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;url&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='nx'&gt;action&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;opensearch&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
        &lt;span class='nx'&gt;format&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;json&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
        &lt;span class='nx'&gt;search&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='nx'&gt;term&lt;/span&gt;
    &lt;span class='p'&gt;})&lt;/span&gt;
    &lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;then&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;data&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='nx'&gt;query&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='nx'&gt;data&lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;],&lt;/span&gt; &lt;span class='nx'&gt;results&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='nx'&gt;data&lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; &lt;span class='p'&gt;};&lt;/span&gt;
    &lt;span class='p'&gt;});&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;

&lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;suggestions&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;distinct&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;flatMapLatest&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;value&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;Bacon&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;fromPromise&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;searchWikipedia&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;value&lt;/span&gt;&lt;span class='p'&gt;));&lt;/span&gt;
&lt;span class='p'&gt;});&lt;/span&gt;

&lt;span class='nx'&gt;suggestions&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;onValue&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;data&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;$results&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;#results&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;&lt;span class='nx'&gt;empty&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt;
    &lt;span class='nx'&gt;data&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;results&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;forEach&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;s&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;&amp;lt;li&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;&lt;span class='nx'&gt;text&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;s&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;&lt;span class='nx'&gt;appendTo&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;$results&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
    &lt;span class='p'&gt;});&lt;/span&gt;
&lt;span class='p'&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here &lt;code&gt;suggestions&lt;/code&gt; is a new stream that has been transformed from strings to search results using the &lt;code&gt;searchWikipedia&lt;/code&gt; function. All of jQuery&amp;#8217;s ajax methods return promises and &lt;code&gt;Bacon.fromPromise()&lt;/code&gt; turns a promise into an event stream.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;flatMapLatest&lt;/code&gt; transformer builds a new stream from an existing stream and a stream factory - and it only emits events from the last stream created. This means that if the user types slowly and a lot of ajax requests are made responses to all but the last request will be disregarded.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;suggestions&lt;/code&gt; stream is ultimately used by calling its &lt;code&gt;onValue&lt;/code&gt; method. That adds a subscriber that runs code for every event that makes it all the way through the stream. The result is a list of search results that is updated live as the user types.&lt;/p&gt;

&lt;p&gt;There are some other tricks available. It is possible to bind data from an event stream to a DOM element:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;query&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;suggestions&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;map&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;data&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;data&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;query&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
&lt;span class='p'&gt;}).&lt;/span&gt;&lt;span class='nx'&gt;toProperty&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;--&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;

&lt;span class='nx'&gt;query&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;assign&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;#query&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;),&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;text&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This creates a new stream that is pared down to just the query used to produce each set of results. Whenever a result set is rendered the corresponding query will also be output as the text content of the &lt;code&gt;&amp;#39;#query&amp;#39;&lt;/code&gt; element. The new stream is converted to a property to make this work. A property is a value that varies over time. The main practical distinction between a property and an event stream is that a property always has a value. In other words a property is &lt;em&gt;continuous&lt;/em&gt; while an event stream is &lt;em&gt;discrete&lt;/em&gt;. This example provides &lt;code&gt;&amp;#39;--&amp;#39;&lt;/code&gt; as the initial value for the new property.&lt;/p&gt;

&lt;p&gt;Notice that property binding as shown here is more general than some data binding frameworks in that the destination is not limited to DOM elements and the source is not limited to model instances. This example passes values to the &lt;code&gt;text&lt;/code&gt; method of the given jQuery object. It is possible to push data to any method on any object.&lt;/p&gt;

&lt;p&gt;Streams can be combined, split, piped, and generally manipulated in all kinds of ways. Properties can be bound, sampled, combined, transformed, or whatever.&lt;/p&gt;

&lt;p&gt;I put this code up on JSFiddle so you can try it out and play with it: &lt;a href='http://jsfiddle.net/hallettj/SqrNT/'&gt;http://jsfiddle.net/hallettj/SqrNT/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are several FRP implementations out there. Two that seem to be prominent are &lt;a href='https://github.com/raimohanska/bacon.js'&gt;Bacon.js&lt;/a&gt; and &lt;a href='https://github.com/Reactive-Extensions/RxJS'&gt;RxJS&lt;/a&gt;. The examples above are code from the RxJS documentation that I rewrote with Bacon. That gave me an opportunity to learn a bit about both libraries and to see how they approach the same problem. The original RxJS code is &lt;a href='https://github.com/Reactive-Extensions/RxJS#why-rxjs'&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;With FRP it is possible to describe complicated processes in a clean, declarative way. FRP is also a natural way to avoid certain classes of race conditions. When I wrote the initial version of the sample code above it worked perfectly on the first try. In my view that is a sign of a very well-designed library.&lt;/p&gt;

&lt;p&gt;If you are interested in further reading I suggest the &lt;a href='http://nullzzz.blogspot.fi/2012/11/baconjs-tutorial-part-i-hacking-with.html'&gt;series of tutorials&lt;/a&gt; from the author of Bacon. And there is a great deal of information on the RxJS and Bacon Github pages, including documentation and more examples.&lt;/p&gt;</content>
 </entry>
 
 
 
 <entry>
   <title>Monkey patching document.write()</title>
   <link href="http://sitr.us/2012/09/04/monkey-patching-document-write.html" />
   <updated>2012-09-04T00:00:00-07:00</updated>
   <id>http://sitr.us/2012/09/04/monkey-patching-document-write</id>
   <content type="html">&lt;p&gt;This is one of the crazier workarounds that I have implemented. I was working on a web page that embeds third-party widgets. The widgets are drawn in the page document - they do not get their own frames. And sometimes the widgets are redrawn after page load.&lt;/p&gt;

&lt;p&gt;We had a problem with one widget invoking &lt;code&gt;document.write()&lt;/code&gt;. In case you are not familiar with it, if that method is called while the page is rendering it inserts content into the DOM immediately after the script tag in which the call is made. But if &lt;code&gt;document.write()&lt;/code&gt; is called after page rendering is complete it erases the entire DOM. When this widget was redrawn after page load it would kill the whole page.&lt;/p&gt;

&lt;p&gt;The workaround we went with was to disable &lt;code&gt;document.write()&lt;/code&gt; after page load by replacing it with a wrapper that checks whether the jQuery ready event has fired.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;originalWrite&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nb'&gt;document&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;write&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
    &lt;span class='nb'&gt;document&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;write&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;typeof&lt;/span&gt; &lt;span class='nx'&gt;jQuery&lt;/span&gt; &lt;span class='o'&gt;!==&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;undefined&amp;#39;&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class='nx'&gt;jQuery&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;isReady&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
            &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;typeof&lt;/span&gt; &lt;span class='nx'&gt;console&lt;/span&gt; &lt;span class='o'&gt;!==&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;undefined&amp;#39;&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class='nx'&gt;console&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;warn&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
                &lt;span class='nx'&gt;console&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;warn&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;document.write called after page load&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
            &lt;span class='p'&gt;}&lt;/span&gt;
        &lt;span class='p'&gt;}&lt;/span&gt;
        &lt;span class='k'&gt;else&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
            &lt;span class='c1'&gt;// In IE before version 8 `document.write()` does not&lt;/span&gt;
            &lt;span class='c1'&gt;// implement Function methods, like `apply()`.&lt;/span&gt;
            &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nb'&gt;Function&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;prototype&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;apply&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;call&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;
                &lt;span class='nx'&gt;originalWrite&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nb'&gt;document&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;arguments&lt;/span&gt;
            &lt;span class='p'&gt;);&lt;/span&gt;
        &lt;span class='p'&gt;}&lt;/span&gt;
    &lt;span class='p'&gt;}&lt;/span&gt;
&lt;span class='p'&gt;})();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The new implementation checks the value of &lt;code&gt;jQuery.isReady&lt;/code&gt; and delegates to the original &lt;code&gt;document.write()&lt;/code&gt; implementation if the page is not finished rendering yet. Otherwise it does nothing other than to output a warning message.&lt;/p&gt;

&lt;p&gt;Disabling &lt;code&gt;document.write()&lt;/code&gt; means that the problematic widget will not be fully functional if it is redrawn after page load. It happens that in the case of this app that is ok. The redrawn widget is only used as a preview when editing widget layouts.&lt;/p&gt;

&lt;p&gt;A particular problem came up with IE compatibility. I wanted to use the &lt;code&gt;apply&lt;/code&gt; method that is implemented by all functions in JavaScript to invoke the original &lt;code&gt;document.write()&lt;/code&gt; implementation, like this:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;originalWrite&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;apply&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;document&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;arguments&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But in older versions of Internet Explorer, &lt;code&gt;document.write()&lt;/code&gt; is not really a function. There are a lot of examples in IE of native API methods and properties that do not behave like regular JavaScript values. For example if you pass too many arguments to a DOM API method in old IE you will get an exception. Normal JavaScript functions just silently ignore extra arguments. If you look at the value of &lt;code&gt;typeof
document.write&lt;/code&gt; the result is not &lt;code&gt;&amp;quot;function&amp;quot;&lt;/code&gt;. What is particularly problematic in this case is that &lt;code&gt;document.write&lt;/code&gt; does not implement &lt;code&gt;call&lt;/code&gt; or &lt;code&gt;apply&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Fortunately I found that the Function prototype does implement both &lt;code&gt;call&lt;/code&gt; and &lt;code&gt;apply&lt;/code&gt; and furthermore you can borrow those methods to use on function-like values like &lt;code&gt;document.write&lt;/code&gt;. &lt;code&gt;call&lt;/code&gt; and &lt;code&gt;apply&lt;/code&gt; are themselves real function values - so &lt;code&gt;call&lt;/code&gt; and &lt;code&gt;apply&lt;/code&gt; both implement &lt;code&gt;call&lt;/code&gt; and &lt;code&gt;apply&lt;/code&gt;.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;span class='k'&gt;typeof&lt;/span&gt; &lt;span class='nb'&gt;Function&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;prototype&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;apply&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;apply&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;apply&lt;/span&gt;  &lt;span class='c1'&gt;// evaluates to &amp;#39;function&amp;#39;&lt;/span&gt;
&lt;span class='k'&gt;typeof&lt;/span&gt; &lt;span class='nb'&gt;Function&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;prototype&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;apply&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;call&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;call&lt;/span&gt;  &lt;span class='c1'&gt;// evaluates to &amp;#39;function&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In the workaround above I applied &lt;code&gt;apply&lt;/code&gt; to &lt;code&gt;document.write&lt;/code&gt; by taking the &lt;code&gt;Function.prototype.apply&lt;/code&gt; value and using its &lt;code&gt;call&lt;/code&gt; method. So this expression,&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;span class='nb'&gt;Function&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;prototype&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;apply&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;call&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;originalWrite&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nb'&gt;document&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;arguments&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;is equivalent to this one,&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;span class='nx'&gt;originalWrite&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;apply&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;document&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;arguments&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Except that the first version works in IE7.&lt;/p&gt;

&lt;p&gt;If you find this difficult to follow, you are not alone.&lt;/p&gt;

&lt;p&gt;We have had this workaround in our code for a couple of years now. So far it is working nicely.&lt;/p&gt;</content>
 </entry>
 
 
 
 
 
 <entry>
   <title>Promise Pipelines in JavaScript</title>
   <link href="http://sitr.us/2012/07/31/promise-pipelines-in-javascript.html" />
   <updated>2012-07-31T00:00:00-07:00</updated>
   <id>http://sitr.us/2012/07/31/promise-pipelines-in-javascript</id>
   <content type="html">&lt;aside class='translations'&gt;This page has been translated into &lt;a href='http://www.webhostinghub.com/support/es/misc/las-bases-de'&gt;Spanish&lt;/a&gt;
language by Maria Ramos  from &lt;a href='http://www.webhostinghub.com/'&gt;Webhostinghub.com&lt;/a&gt;.&lt;/aside&gt;
&lt;p&gt;Promises, also know as deferreds or futures, are a wonderful abstraction for manipulating asynchronous actions. Dojo has had &lt;a href='http://dojotoolkit.org/reference-guide/1.7/dojo/Deferred.html'&gt;Deferreds&lt;/a&gt; for some time. jQuery introduced &lt;a href='http://api.jquery.com/category/deferred-object/'&gt;its own Deferreds&lt;/a&gt; in version 1.5 based on the CommonJS &lt;a href='http://wiki.commonjs.org/wiki/Promises/A'&gt;Promises/A&lt;/a&gt; specification. I&amp;#8217;m going to show you some recipes for working with jQuery Deferreds. Use these techniques to turn callback-based spaghetti code into elegant declarative code.&lt;/p&gt;

&lt;h2 id='the_basics_of_jquery_deferreds'&gt;The basics of jQuery Deferreds&lt;/h2&gt;

&lt;p&gt;A Deferred is an object that represents some future outcome. Eventually it will either resolve with one or more values if that outcome was successful; or it will fail with one or more values if the outcome was not successful. You can get at those resolved or failed values by adding callbacks to the Deferred.&lt;/p&gt;

&lt;p&gt;In jQuery&amp;#8217;s terms a promise is a read-only view of a deferred.&lt;/p&gt;

&lt;p&gt;Here is a simple example of creating and then resolving a promise:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;span class='kd'&gt;function&lt;/span&gt; &lt;span class='nx'&gt;fooPromise&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;deferred&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;Deferred&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt;

    &lt;span class='nx'&gt;setTimeout&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='nx'&gt;deferred&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;resolve&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
    &lt;span class='p'&gt;},&lt;/span&gt; &lt;span class='mi'&gt;1000&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;

    &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;deferred&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;promise&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Callbacks can be added to a deferred or a promise using the &lt;code&gt;.then()&lt;/code&gt; method. The first callback is called on success, the second on failure:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;span class='nx'&gt;fooPromise&lt;/span&gt;&lt;span class='p'&gt;().&lt;/span&gt;&lt;span class='nx'&gt;then&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;
    &lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;value&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='c1'&gt;// prints &amp;quot;foo&amp;quot; after 1 second&lt;/span&gt;
        &lt;span class='nx'&gt;console&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;log&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;value&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
    &lt;span class='p'&gt;},&lt;/span&gt;
    &lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='nx'&gt;console&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;log&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;something went wrong&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt;
&lt;span class='p'&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;For more information see the &lt;a href='http://api.jquery.com/category/deferred-object/'&gt;jQuery Deferred documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Note that if you are using a version of jQuery prior to 1.8 you will have to use &lt;code&gt;.pipe()&lt;/code&gt; instead of &lt;code&gt;.then()&lt;/code&gt;. That goes for all references to &lt;code&gt;.then()&lt;/code&gt; in this article.&lt;/p&gt;

&lt;h2 id='sequential_operations'&gt;Sequential operations&lt;/h2&gt;

&lt;p&gt;Actions, such as HTTP requests, need to be sequential if input to one action depends on the output of another; or if you just want to make sure that actions are performed in a particular order.&lt;/p&gt;

&lt;p&gt;Consider a scenario where you have a post id and you want to display information about the author of that post. Your web services don&amp;#8217;t support embedding author information in a post resource. So you will have to download data on the post, get the author id, and then make another request to get data for the author. To start with you will want functions for downloading a post and a user:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;span class='kd'&gt;function&lt;/span&gt; &lt;span class='nx'&gt;getPost&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;id&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;getJSON&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;/posts/&amp;#39;&lt;/span&gt;&lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='nx'&gt;id&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;&lt;span class='nx'&gt;then&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;data&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;status&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;xhr&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;data&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
    &lt;span class='p'&gt;});&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;

&lt;span class='kd'&gt;function&lt;/span&gt; &lt;span class='nx'&gt;getUser&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;id&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;getJSON&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;/users/&amp;#39;&lt;/span&gt;&lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='nx'&gt;id&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;&lt;span class='nx'&gt;then&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;data&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;status&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;xhr&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;data&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
    &lt;span class='p'&gt;});&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In jQuery 1.5 and later all ajax methods return a promise that, on a successful request, resolves with the data in the response, the response status, and the XHR object representing the request.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;.then()&lt;/code&gt; method produces a new promise that transforms the resolved value of its input. I used &lt;code&gt;.then()&lt;/code&gt; here just because using &lt;code&gt;$.when()&lt;/code&gt; is simpler if each promise resolves to a single value. We will get back to that in parallel operations. Since only one argument is provided to &lt;code&gt;.then()&lt;/code&gt; in these cases the new promises will have the same error values as the originals if an error occurs.&lt;/p&gt;

&lt;p&gt;The result is that &lt;code&gt;getUser()&lt;/code&gt; returns a promise that should resolve to data representing the user profile for a given id. And &lt;code&gt;getPost()&lt;/code&gt; works the same way for posts and post ids.&lt;/p&gt;

&lt;p&gt;Now, to fetch that author information:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;span class='kd'&gt;function&lt;/span&gt; &lt;span class='nx'&gt;authorForPost&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;id&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;postPromise&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;getPost&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;id&lt;/span&gt;&lt;span class='p'&gt;),&lt;/span&gt;
        &lt;span class='nx'&gt;deferred&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;Deferred&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt;

    &lt;span class='nx'&gt;postPromise&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;then&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;post&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;authorPromise&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;getUser&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;post&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;authorId&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;

        &lt;span class='nx'&gt;authorPromise&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;then&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;author&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
            &lt;span class='nx'&gt;deferred&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;resolve&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;author&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
        &lt;span class='p'&gt;});&lt;/span&gt;
    &lt;span class='p'&gt;});&lt;/span&gt;

    &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;deferred&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;promise&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When &lt;code&gt;authorForPost()&lt;/code&gt; is called it returns a new promise that resolves with author information after both the post and author requests complete successfully. This is a straightforward way to get the job done. Though it does not implement error handling; and it could be more &lt;a href='https://en.wikipedia.org/wiki/Don&amp;apos;t_repeat_yourself'&gt;DRY&lt;/a&gt;. More on that in a bit.&lt;/p&gt;

&lt;h2 id='parallel_operations'&gt;Parallel operations&lt;/h2&gt;

&lt;p&gt;Let&amp;#8217;s say that you want to fetch two user profiles to display side-by-side. Using the &lt;code&gt;getUser()&lt;/code&gt; function from the previous section:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;span class='kd'&gt;function&lt;/span&gt; &lt;span class='nx'&gt;getTwoUsers&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;idA&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;idB&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;userPromiseA&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;getUser&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;idA&lt;/span&gt;&lt;span class='p'&gt;),&lt;/span&gt;
        &lt;span class='nx'&gt;userPromiseB&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;getUser&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;idB&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;

    &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;when&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;userPromiseA&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;userPromiseB&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The requests for userA and userB&amp;#8217;s profiles will be made in parallel so that you can get the results back as quickly as possible. This function uses &lt;code&gt;$.when()&lt;/code&gt; to synchronize the promises for each profile so that &lt;code&gt;getTwoUsers()&lt;/code&gt; returns one promise that resolves with the data for both profiles when both responses come back. If either request fails, the promise that &lt;code&gt;getTwoUsers()&lt;/code&gt; returns will fail with information about the first failed request.&lt;/p&gt;

&lt;p&gt;You might use &lt;code&gt;getTwoUsers()&lt;/code&gt; like this:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;span class='nx'&gt;getTwoUsers&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='mi'&gt;1002&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;1008&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;&lt;span class='nx'&gt;then&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;userA&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;userB&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;render&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;userA&lt;/span&gt;&lt;span class='p'&gt;)).&lt;/span&gt;&lt;span class='nx'&gt;appendTo&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;#users&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
    &lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;render&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;userB&lt;/span&gt;&lt;span class='p'&gt;)).&lt;/span&gt;&lt;span class='nx'&gt;appendTo&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;#users&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
&lt;span class='p'&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;getTwoUsers()&lt;/code&gt; promise resolves with two values, one for each profile.&lt;/p&gt;

&lt;p&gt;We now have several well-defined functions that operate on asynchronous actions. Isn&amp;#8217;t this nicer than the big mess of nested callbacks one might otherwise see?&lt;/p&gt;

&lt;p&gt;I mentioned above that using &lt;code&gt;$.when()&lt;/code&gt; is simpler when each of its input promises resolves to a single value. That is because if an input promise resolves to multiple values then the corresponding value in the new promise that &lt;code&gt;$.when()&lt;/code&gt; creates will be an array instead of a single value.&lt;/p&gt;

&lt;p&gt;Performing an arbitrary number of actions in parallel is similar:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;span class='kd'&gt;function&lt;/span&gt; &lt;span class='nx'&gt;getPosts&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;ids&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;postPromises&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;ids&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;map&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;getPost&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;

    &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;when&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;apply&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;postPromises&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;&lt;span class='nx'&gt;then&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='cm'&gt;/* posts... */&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;makeArray&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;arguments&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
    &lt;span class='p'&gt;});&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This code fetches any number of posts in parallel. I used &lt;code&gt;apply&lt;/code&gt; to pass the post promises to &lt;code&gt;$.when()&lt;/code&gt; as though they are each a separate argument. The resulting promise resolves with a separate value for each post. It would be nicer if it resolved with an array of posts as one value. The use of &lt;code&gt;.then()&lt;/code&gt; here takes those post values and transforms them into an array.&lt;/p&gt;

&lt;h2 id='combining_sequential_and_parallel_operations'&gt;Combining sequential and parallel operations&lt;/h2&gt;

&lt;p&gt;Let&amp;#8217;s take the previous examples to their logical conclusion by creating a function that, given two post ids, will download information about the authors of each post to display them side-by-side. No problem!&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;span class='kd'&gt;function&lt;/span&gt; &lt;span class='nx'&gt;getAuthorsForTwoPosts&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;idA&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;idB&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;when&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;authorForPost&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;idA&lt;/span&gt;&lt;span class='p'&gt;),&lt;/span&gt; &lt;span class='nx'&gt;authorForPost&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;idB&lt;/span&gt;&lt;span class='p'&gt;));&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;From the perspective of a function that calls &lt;code&gt;authorForPost()&lt;/code&gt;, it does not matter that two sequential requests are made. Because &lt;code&gt;authorForPost()&lt;/code&gt; returns a promise that represents the eventual result of both requests, that detail is encapsulated.&lt;/p&gt;

&lt;h2 id='generalizing_sequential_operations'&gt;Generalizing sequential operations&lt;/h2&gt;

&lt;p&gt;There are a couple of problems with the implementation of &lt;code&gt;authorForPost()&lt;/code&gt; as presented above. We had to create a deferred by hand, which should not be necessary. And the promise that is returned does not fail if any of the requests involved fail.&lt;/p&gt;

&lt;p&gt;These issues are not present in the parallel examples because &lt;code&gt;$.when()&lt;/code&gt; does a nice job of generalizing synchronizing multiple promises. What we need is a function that does a similar job of generalizing flattening nested promises. Meet flatMap:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;flatMap&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;promise&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;f&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;deferred&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;Deferred&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt;

    &lt;span class='kd'&gt;function&lt;/span&gt; &lt;span class='nx'&gt;reject&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='cm'&gt;/* arguments */&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='c1'&gt;// The reject() method puts a deferred into its failure&lt;/span&gt;
        &lt;span class='c1'&gt;// state.&lt;/span&gt;
        &lt;span class='nx'&gt;deferred&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;reject&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;apply&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;deferred&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;arguments&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
    &lt;span class='p'&gt;}&lt;/span&gt;

    &lt;span class='nx'&gt;promise&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;then&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='cm'&gt;/* values... */&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;newPromise&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;f&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;apply&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;arguments&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;

        &lt;span class='nx'&gt;newPromise&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;then&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='cm'&gt;/* newValues... */&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
            &lt;span class='nx'&gt;deferred&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;resolve&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;apply&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;deferred&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;arguments&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
        &lt;span class='p'&gt;},&lt;/span&gt; &lt;span class='nx'&gt;reject&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;

    &lt;span class='p'&gt;},&lt;/span&gt; &lt;span class='nx'&gt;reject&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;

    &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;deferred&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;promise&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt;
&lt;span class='p'&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This function takes a promise and a callback that returns another promise. When the first promise resolves, &lt;code&gt;$.flatMap()&lt;/code&gt; invokes the callback with the resolved values as arguments, which produces a new promise. When that new promise resolves, the promise that &lt;code&gt;$.flatMap()&lt;/code&gt; returns also resolves with the same values. On top of that, &lt;code&gt;$.flatMap()&lt;/code&gt; forwards errors to the promise that it returns. If either the input promise or the promise returned by the callback fails then the promise that &lt;code&gt;$.flatMap()&lt;/code&gt; returns will fail with the same values.&lt;/p&gt;

&lt;p&gt;Using &lt;code&gt;$.flatMap()&lt;/code&gt; it is possible to write a function like &lt;code&gt;authorForPost()&lt;/code&gt; a bit more succinctly:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;span class='kd'&gt;function&lt;/span&gt; &lt;span class='nx'&gt;authorForPost&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;id&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;flatMap&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;getPost&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;id&lt;/span&gt;&lt;span class='p'&gt;),&lt;/span&gt; &lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;post&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;getUser&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;post&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;authorId&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
    &lt;span class='p'&gt;});&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;By using &lt;code&gt;$.flatMap()&lt;/code&gt; you also get error handling for free. If the request to fetch a post fails or the request to fetch the post&amp;#8217;s author fails the promise that this version of &lt;code&gt;authorForPost()&lt;/code&gt; returns will also fail with the appropriate failure values.&lt;/p&gt;

&lt;p&gt;Another potential problem is that &lt;code&gt;authorForPost()&lt;/code&gt; does not give you access to any of the information on the posts that it downloads. You can combine &lt;code&gt;$.flatMap()&lt;/code&gt; and &lt;code&gt;.then()&lt;/code&gt; to create a slightly different function that exposes both the post and the author:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;span class='kd'&gt;function&lt;/span&gt; &lt;span class='nx'&gt;postWithAuthor&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;id&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;flatMap&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;getPost&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;id&lt;/span&gt;&lt;span class='p'&gt;),&lt;/span&gt; &lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;post&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;getUser&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;post&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;authorId&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;&lt;span class='nx'&gt;then&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;author&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
            &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;extend&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;post&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='nx'&gt;author&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='nx'&gt;author&lt;/span&gt; &lt;span class='p'&gt;});&lt;/span&gt;
        &lt;span class='p'&gt;});&lt;/span&gt;
    &lt;span class='p'&gt;});&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The promise that &lt;code&gt;postWithAuthor()&lt;/code&gt; returns resolves to a post object with an added author property containing author information.&lt;/p&gt;

&lt;p&gt;It turns out that &lt;code&gt;.then()&lt;/code&gt; leads a double life. If the return value of its callback is a promise, &lt;code&gt;.then()&lt;/code&gt; behaves exactly like &lt;code&gt;$.flatMap()&lt;/code&gt;! This is the sort of thing that only a dynamic language like JavaScript can do. So if you want to skip the custom function, you could write &lt;code&gt;postWithAuthor()&lt;/code&gt; like this:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;span class='kd'&gt;function&lt;/span&gt; &lt;span class='nx'&gt;postWithAuthor&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;id&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;getPost&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;id&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;&lt;span class='nx'&gt;then&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;post&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;getUser&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;post&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;authorId&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;&lt;span class='nx'&gt;then&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;author&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
            &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;extend&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;post&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='nx'&gt;author&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='nx'&gt;author&lt;/span&gt; &lt;span class='p'&gt;});&lt;/span&gt;
        &lt;span class='p'&gt;});&lt;/span&gt;
    &lt;span class='p'&gt;});&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id='other_uses_for_promises'&gt;Other uses for promises&lt;/h2&gt;

&lt;p&gt;The examples above focus on HTTP requests. But promises can be used in any kind of asynchronous code. They even come in handy in synchronous code from time to time.&lt;/p&gt;

&lt;p&gt;Here is an example of a promise used to represent the outcome of a series of user interactions:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;span class='kd'&gt;function&lt;/span&gt; &lt;span class='nx'&gt;getRegistrationDetails&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;detailsPromise&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;openModal&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;get&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;/registrations&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;));&lt;/span&gt;

    &lt;span class='nx'&gt;detailsPromise&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;then&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;details&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;post&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;/registrations&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;details&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
    &lt;span class='p'&gt;});&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;

&lt;span class='kd'&gt;function&lt;/span&gt; &lt;span class='nx'&gt;openModal&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;markupPromise&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;deferred&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;Deferred&lt;/span&gt;&lt;span class='p'&gt;(),&lt;/span&gt;
        &lt;span class='nx'&gt;modal&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;&amp;lt;div&amp;gt;&amp;lt;/div&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;&lt;span class='nx'&gt;addClass&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;modalWindow&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;),&lt;/span&gt;
        &lt;span class='nx'&gt;loadingSpinner&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;&amp;lt;span&amp;gt;&amp;lt;/span&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;&lt;span class='nx'&gt;addClass&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;spinner&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;

    &lt;span class='nx'&gt;modal&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;append&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;loadingSpinner&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;

    &lt;span class='c1'&gt;// Use .always() to add a callback to a promise that runs on success&lt;/span&gt;
    &lt;span class='c1'&gt;// or failure.&lt;/span&gt;
    &lt;span class='nx'&gt;markupPromise&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;always&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='nx'&gt;loadingSpinner&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;remove&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt;
    &lt;span class='p'&gt;});&lt;/span&gt;

    &lt;span class='nx'&gt;markupPromise&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;then&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;markup&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='nx'&gt;modal&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;html&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;markup&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
    &lt;span class='p'&gt;});&lt;/span&gt;

    &lt;span class='nx'&gt;modal&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;one&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;submit&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;form&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;event&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='nx'&gt;event&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;preventDefault&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt;
        &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;data&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;&lt;span class='nx'&gt;serialize&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt;
        &lt;span class='nx'&gt;modal&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;remove&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt;
        &lt;span class='nx'&gt;deferred&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;resolve&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;data&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
    &lt;span class='p'&gt;});&lt;/span&gt;

    &lt;span class='nx'&gt;modal&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;appendTo&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;body&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;

    &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;deferred&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;promise&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;

&lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nb'&gt;document&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;&lt;span class='nx'&gt;ready&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;#registerButton&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;&lt;span class='nx'&gt;click&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;event&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='nx'&gt;event&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;preventDefault&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt;
        &lt;span class='nx'&gt;getRegistrationDetails&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt;
    &lt;span class='p'&gt;});&lt;/span&gt;
&lt;span class='p'&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I suggest considering using promises anywhere you would otherwise pass a callback as an argument.&lt;/p&gt;

&lt;h2 id='conclusion'&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;The promise transformations &lt;code&gt;.then()&lt;/code&gt;, &lt;code&gt;$.when()&lt;/code&gt;, and &lt;code&gt;$.flatMap()&lt;/code&gt; work together to build promise pipelines. Using these functions you can define arbitrary parallel and sequential operations with nice declarative code. Furthermore, small promise pipelines can be encapsulated in helper functions which can be composed to form longer pipelines. This promotes reusability and maintainability in your code.&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;.then()&lt;/code&gt; to transform individual promises.&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;$.when()&lt;/code&gt; to synchronize parallel operations.&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;$.flatMap()&lt;/code&gt; or &lt;code&gt;.then()&lt;/code&gt; to create chains of sequential operations.&lt;/p&gt;

&lt;p&gt;Mix and match as desired.&lt;/p&gt;

&lt;p&gt;I would like to thank &lt;a href='https://github.com/munro'&gt;Ryan Munro&lt;/a&gt; for coming up with the &amp;#8220;pipeline&amp;#8221; analogy.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Update 2012-08-01:&lt;/em&gt; &lt;code&gt;.pipe()&lt;/code&gt; was added in jQuery 1.6. And it turns out that it behaves like &lt;code&gt;$.flatMap()&lt;/code&gt; when its callback returns a promise. In jQuery 1.8 &lt;code&gt;.then()&lt;/code&gt; will be updated to behave exactly like &lt;code&gt;.pipe()&lt;/code&gt;, and &lt;code&gt;.pipe()&lt;/code&gt; will be deprecated. So there is actually no need to add a custom method - you can just use &lt;code&gt;.pipe()&lt;/code&gt; or &lt;code&gt;.then()&lt;/code&gt; instead of &lt;code&gt;$.flatMap()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Update 2013-01-30:&lt;/em&gt; jQuery 1.8 has been released, so I replaced references to &lt;code&gt;.pipe()&lt;/code&gt; with &lt;code&gt;.then()&lt;/code&gt;. I also included a more prominent explanation that &lt;code&gt;.then()&lt;/code&gt; can do the same thing that &lt;code&gt;$.flatMap()&lt;/code&gt; does.&lt;/p&gt;

&lt;h2 id='promises_and_category_theory'&gt;Promises and Category theory&lt;/h2&gt;

&lt;p&gt;Good news! If you are able to follow the examples in this post then you have a working understanding of Monads. Specifically, &lt;code&gt;$.flatMap()&lt;/code&gt; is a &lt;a href='http://en.wikipedia.org/wiki/Monad_(functional_programming)'&gt;monad&lt;/a&gt; transformation, &lt;code&gt;.then()&lt;/code&gt; with one argument is a &lt;a href='http://en.wikipedia.org/wiki/Functor'&gt;functor&lt;/a&gt; transformation, and &lt;code&gt;$.when()&lt;/code&gt; is almost a &lt;a href='http://en.wikipedia.org/wiki/Monoid'&gt;monoid&lt;/a&gt; transformation.&lt;/p&gt;

&lt;p&gt;Monads, monoids, and functors are concepts from &lt;a href='http://en.wikipedia.org/wiki/Category_theory'&gt;category theory&lt;/a&gt; that can be applied to functional programming. Really they are just generalizations of this idea of creating pipelines to transform values.&lt;/p&gt;

&lt;p&gt;I bring this up because category theory can be useful, but is difficult to explain. My hope is that seeing examples of category theory in action will help programmers to get a feel for the patterns involved.&lt;/p&gt;

&lt;p&gt;For more information on category theory in programming I recommend a series of blog posts titled &lt;a href='http://james-iry.blogspot.com/2007/09/monads-are-elephants-part-1.html'&gt;Monads are Elephants&lt;/a&gt;. If you have read that and want to go further, I found the the book &lt;a href='http://learnyouahaskell.com/'&gt;Learn You a Haskell for Great Good!&lt;/a&gt; to be very informative. And as a bonus it teaches you Haskell.&lt;/p&gt;

&lt;p&gt;Those who are already into category theory will note that &lt;code&gt;$.flatMap()&lt;/code&gt; could also be defined in terms of &lt;code&gt;.then()&lt;/code&gt; and a &lt;code&gt;$.join()&lt;/code&gt; function:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;flatMap&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;promise&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;f&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;join&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;promise&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;then&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;f&lt;/span&gt;&lt;span class='p'&gt;));&lt;/span&gt;
&lt;span class='p'&gt;};&lt;/span&gt;

&lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;join&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;promise&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;deferred&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;$&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;Deferred&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt;

    &lt;span class='kd'&gt;function&lt;/span&gt; &lt;span class='nx'&gt;reject&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='cm'&gt;/* arguments */&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='nx'&gt;deferred&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;reject&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;apply&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;deferred&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;arguments&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
    &lt;span class='p'&gt;}&lt;/span&gt;

    &lt;span class='nx'&gt;promise&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;then&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;nestedPromise&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;

        &lt;span class='nx'&gt;nestedPromise&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;then&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='cm'&gt;/* values... */&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
            &lt;span class='nx'&gt;deferred&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;resolve&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;apply&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;deferred&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;arguments&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
        &lt;span class='p'&gt;},&lt;/span&gt; &lt;span class='nx'&gt;reject&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;

    &lt;span class='p'&gt;},&lt;/span&gt; &lt;span class='nx'&gt;reject&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;

    &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;deferred&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;promise&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt;
&lt;span class='p'&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Except that this won&amp;#8217;t actually work because &lt;code&gt;.then()&lt;/code&gt; will join the inner and outer promises before the result is passed to &lt;code&gt;$.join()&lt;/code&gt;.&lt;/p&gt;</content>
 </entry>
 
 
 
 <entry>
   <title>Installing a custom ROM on the Transformer Prime: A start-to-finish guide</title>
   <link href="http://sitr.us/2012/05/12/installing-a-custom-rom-on-the-transformer-prime.html" />
   <updated>2012-05-12T00:00:00-07:00</updated>
   <id>http://sitr.us/2012/05/12/installing-a-custom-rom-on-the-transformer-prime</id>
   <content type="html">&lt;p&gt;This guide provides step-by-step instructions for installing the &lt;a href='http://www.virtuousrom.com/p/prime.html'&gt;Virtuous Prime&lt;/a&gt; community ROM on your Asus Transformer Prime TF201 tablet. This guide will be useful to you if you do not have root access to your tablet.&lt;/p&gt;

&lt;p&gt;Be aware that following the instructions here will void your warranty and will wipe all of the data on your tablet. There is also a danger that you might brick your tablet. Proceed at your own risk.&lt;/p&gt;

&lt;p&gt;So, why would you want to install a custom ROM on your tablet? In my case I wanted to gain root access, which allows one to do all sorts of nifty things. Community-made ROMS are also often customized to make the Android experience more pleasant for power users. And choosing your own ROM means that you are no longer dependent on the company that sold you your device to distribute firmware updates in a timely fashion. But if you are reading this then you probably already know why you want to install a custom ROM - so let&amp;#8217;s get on to the next step.&lt;/p&gt;

&lt;p&gt;This guide specifically covers installing &lt;a href='http://www.virtuousrom.com/p/prime.html'&gt;Virtuous Prime&lt;/a&gt;, which is based on the official Asus firmware. If you like the features that Asus provides, like the ability to switch between performance profiles and to toggle IPS+ mode then this is probably the ROM for you. Virtuous also adds some features like root access, the ability to overclock the processors to 1.6 GHz, and so on. Note to the Virtuous ROM devs: it is really awesome to have you all putting in the effort to make the Android experience better for everybody. It is especially amazing that you give your ROM away for free. You are virtuous people indeed! That said, these folks do accept &lt;a href='https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&amp;amp;hosted_button_id=DLXKH3V45FFYY'&gt;donations&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you would rather get a vanilla Ice Cream Sandwich experience then you might check out &lt;a href='http://transformerprimeroot.com/transformer-prime-roms/aokp-ics-rom-for-rooted-transformer-prime/'&gt;AOKP&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you just want root access and you do not want to install a custom ROM then there is a simpler procedure that you can follow using &lt;a href='http://forum.xda-developers.com/showthread.php?t=1526487'&gt;SparkyRoot&lt;/a&gt;. The catch is that SparkyRoot does not work in firmware versions v9.4.2.21 or later. Part of the reason that I went for a custom ROM is that I upgraded the firmware on my Prime as soon as I got it - so I missed my shot at using SparkyRoot. Don&amp;#8217;t be like me: plan ahead!&lt;/p&gt;

&lt;p&gt;If you have the newest firmware version &lt;a href='http://forum.xda-developers.com/showthread.php?t=1622628'&gt;it is possible to downgrade&lt;/a&gt; in order to use SparkyRoot. I chose to install a custom ROM instead because it seemed to me to be a safer option. Be aware that if you follow the directions here to install a custom ROM you will not be able to use the downgrade procedure in that link.&lt;/p&gt;

&lt;p&gt;In brief, here are the steps that we are going to follow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Unlock the bootloader using the official Asus tool.&lt;/li&gt;

&lt;li&gt;Install ClockworkMod Recovery.&lt;/li&gt;

&lt;li&gt;Install the Virtuous Prime ROM, using ClockworkMod.&lt;/li&gt;
&lt;/ol&gt;
&lt;div style='margin-top:2em' /&gt;
&lt;h2 id='step_1_unlock_the_bootloader'&gt;Step 1: Unlock the bootloader&lt;/h2&gt;

&lt;p&gt;I am not completely sure that this step is necessary. I did not try installing ClockworkMod Recovery before unlocking. But even if it is not necessary, I imagine that there may come a time when I am glad to have an unlocked bootloader. You can try skipping this step; at worst nothing will happen.&lt;/p&gt;

&lt;p&gt;The unlocking tool is provided by Asus. As you will see, Asus makes it very clear that using the unlock tool will void your warranty. But on the upside it will not wipe your data or anything like that. The only noticeable change will be that every time you boot up the tablet there will be a message in the upper-left corner of the screen that says, &amp;#8220;The device is UnLocked&amp;#8221;. I assume that is there so that customer service representatives can see that they are not supposed to help you.&lt;/p&gt;

&lt;p&gt;Download the unlock tool directly onto your tablet from &lt;a href='http://support.asus.com/Download.aspx?SLanguage=en&amp;amp;m=Eee+Pad+Transformer+Prime+TF201&amp;amp;p=20&amp;amp;s=16'&gt;the TF201 support section&lt;/a&gt; of the Asus website. Select &amp;#8220;Android&amp;#8221; as the OS and grab the &amp;#8220;Unlock Device App&amp;#8221; from the &amp;#8220;Utilities&amp;#8221; section. The file that you get is an apk that you will install as an app.&lt;/p&gt;

&lt;p&gt;If you have not done so already, you will have to enable unknown software sources in your tablet settings. Go to Settings &amp;gt; Security &amp;gt; Device Administration and check the box that says &amp;#8220;Unknown Sources&amp;#8221;.&lt;/p&gt;

&lt;p&gt;Use your file manager to find the downloaded unlock tool. It is probably in &lt;code&gt;/sdcard/Download/UnLock_Device_App_V6.apk&lt;/code&gt;. Tap it to install the app.&lt;/p&gt;

&lt;p&gt;You will be prompted to confirm your Google account by entering your Google password. If you are using two-factor authentication on your Google account you will have to set up an application-specific password for this. You can revoke that password after your tablet is unlocked.&lt;/p&gt;

&lt;p&gt;Next you will have to agree to a license and acknowledge a warning. Again, Asus wants to make it really clear that you are about to void your warranty.&lt;/p&gt;

&lt;p&gt;After you agree to everything your tablet will reboot and your bootloader is now unlocked.&lt;/p&gt;

&lt;h2 id='step_2_install_clockworkmod_recovery'&gt;Step 2: Install ClockworkMod Recovery&lt;/h2&gt;

&lt;p&gt;ClockworkMod Recovery is a custom recovery image. The Transformer Prime comes with a recovery image provided by Asus that lets you do stuff like manually install OS updates. But the Asus recovery image will only let you install updates that are digitally signed by Asus. To install a community-made ROM you need a recovery mode that will let you install unsigned ROMs. That is what ClockworkMod does. It also provides extra features, like the ability to back up and restore your whole OS.&lt;/p&gt;

&lt;p&gt;Installing ClockworkMod will probably void your warranty - in case you somehow got to this point with an intact warranty. There is also some danger that you could brick your tablet. Proceed at your own risk.&lt;/p&gt;

&lt;p&gt;These instructions are adapted from &lt;a href='http://transformerprimeroot.com/transformer-prime-recovery/how-to-install-clockworkmod-recovery-5-8-2-0-on-transformer-prime/'&gt;a guide on TransformerPrimeRoot.com&lt;/a&gt;. I&amp;#8217;m going to give you the slightly more complicated version that involves downloading files directly from ClockworkMod and from Google; and I will provide tips on what to do if the fastboot tool is not able to find your tablet. I personally appreciate it when I can get files from sources that I know I can trust. But if you are not convinced that is necessary then feel free to check out the TransformerPrimeRoot.com guide.&lt;/p&gt;

&lt;p&gt;For this step you will need a computer.&lt;/p&gt;

&lt;p&gt;Download the latest ClockworkMod Recovery image from &lt;a href='http://www.clockworkmod.com/rommanager'&gt;ClockworkMod&amp;#8217;s downloads page&lt;/a&gt;. As of this writing the latest version for the Transformer Prime is 5.8.2.0. According to TransformerPrimeRoot.com earlier versions can put your device into a reboot loop (which you can recover from but it is scary when it happens, I imagine).&lt;/p&gt;

&lt;p&gt;The Touch Recovery image should also work. It comes with a nicer touch-based UI. But the guides that I have read call for the non-touch version, so that is what I went with.&lt;/p&gt;

&lt;p&gt;You will also need the fastboot tool from the Android SDK to install the recovery image. &lt;a href='https://developer.android.com/sdk/index.html'&gt;Download the SDK&lt;/a&gt; from Google and extract it. Run the &lt;code&gt;android&lt;/code&gt; executable in the &lt;code&gt;tools/&lt;/code&gt; directory to launch the SDK package manager and use that tool to install the Android SDK Platform-tools: check the box next to &amp;#8220;Android SDK Platform-tools&amp;#8221; and click &amp;#8220;Install packages&amp;#8230;&amp;#8221;. After a few minutes that will add a new executable, &lt;code&gt;fastboot&lt;/code&gt;, in the &lt;code&gt;platform-tools&lt;/code&gt; directory in the Android SDK package. You will use the fastboot program to send commands to your tablet while the tablet is in fastboot mode.&lt;/p&gt;

&lt;p&gt;Android devices have two boot modes apart from the normal boot-into-the-OS option: &lt;a href='http://www.androidcentral.com/what-recovery-android-z'&gt;recovery mode&lt;/a&gt; and &lt;a href='http://www.androidcentral.com/android-z-what-fastboot'&gt;fastboot&lt;/a&gt;. Fastboot is a low-level mode that is used for flashing firmware. You can use fastboot to replace the recovery mode image - which is what we will be doing to install ClockworkMod. And you can use recovery mode to install a new OS. Likewise, if your OS breaks you can fix it from recovery mode and if recovery mode breaks you may be able to fix it from fastboot. What happens if fastboot breaks? Try not to let that happen! The Android devs have not yet provided us with an extra-fast-boot.&lt;/p&gt;

&lt;p&gt;If you are on Windows then you will have to &lt;a href='http://transformerprimeroot.com/transformer-prime-root/how-to-install-transformer-prime-usb-drivers-on-windows/'&gt;install a USB driver&lt;/a&gt; before proceeding. Linux and Mac users do not need any special drivers.&lt;/p&gt;

&lt;p&gt;Make sure that your battery is charged to at least 50%. Bad things will happen if your battery dies while you are flashing a recovery image.&lt;/p&gt;

&lt;p&gt;Boot your tablet into fastboot by holding down the power and volume-down buttons. The tablet will power off and reboot. Wait until you see several lines of white text in the upper-left corner of the screen, then let go of the power and volume buttons. Then wait for five seconds and you will see the fastboot options.&lt;/p&gt;

&lt;p&gt;Press volume-down to highlight the USB icon and then press volume-up to select it. You have ten seconds to do this - after that the tablet will cold-boot Android instead. If that happens, don&amp;#8217;t worry. Just start over by holding down the power and volume-down buttons.&lt;/p&gt;

&lt;p&gt;Plug the tablet into your computer using the USB cable that came with your tablet.&lt;/p&gt;

&lt;p&gt;On your computer open a terminal. Assuming that you have the ClockworkMod Recovery image and the extracted Android SDK in the same downloads folder, cd to that folder. Run this fastboot command to make sure that your computer is talking to your tablet:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;android-sdk_r18/platform-tools/fastboot -i 0x0b05&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;-i 0x0b05&lt;/code&gt; part tells fastboot which USB device to communicate with. The number &lt;code&gt;0b05&lt;/code&gt; is the Asus vendor id for USB interfaces. If you want to double-check that vendor id you can use the &lt;code&gt;lsusb&lt;/code&gt; command on Linux. On my machine the output includes a line that looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Bus 002 Device 018: ID 0b05:4d01 ASUSTek Computer, Inc.&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The vendor id is the portion of the ID before the colon.&lt;/p&gt;

&lt;p&gt;Anyway, if the fastboot command that you ran worked you should see output that looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;finished. total time: 1336881627.143s&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;On the other hand, if you see a message that says &lt;code&gt;&amp;lt; waiting for device &amp;gt;&lt;/code&gt;, and you wait a minute or two and nothing happens, then hit Ctrl-c to cancel. If you are in Linux you can fix this problem by creating a udev rule. Create a new file, &lt;code&gt;/etc/udev/rules.d/99-android.rules&lt;/code&gt; and add this line to it:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;SUBSYSTEM==&amp;quot;usb&amp;quot;, ATTRS{idVendor}==&amp;quot;0b05&amp;quot;, MODE=&amp;quot;0666&amp;quot;, OWNER=&amp;quot;yourusername&amp;quot;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But make sure to replace &amp;#8220;yourusername&amp;#8221; with your user name. Then restart udev with this command:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo restart udev&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now try the fastboot command again.&lt;/p&gt;

&lt;p&gt;Ok, is fastboot talking to your tablet? Now for the next step: flashing ClockworkMod.&lt;/p&gt;

&lt;p&gt;I recommend checking the md5 checksum on the ClockworkMod Recovery image to make sure that it has not been corrupted. On Linux you can use this command to do that:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;md5sum recovery-clockwork-5.8.2.0-tf201.img&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It appears that ClockworkMod does not list md5 checksums on its downloads page. But here is the checksum that I got for version 5.8.2.0:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;08009bd8fa324116e71982945390cdde&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You should proceed only if the checksums match.&lt;/p&gt;

&lt;p&gt;Run this command - and again make sure that the paths match the locations of the fastboot and ClockworkMod Recovery image files:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;android-sdk_r18/platform-tools/fastboot -i 0x0b05 flash recovery recovery-clockwork-5.8.2.0-tf201.img &lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If all goes well you should see some output like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sending &amp;#39;recovery&amp;#39; (5378 KB)...
OKAY [  1.891s]
writing &amp;#39;recovery&amp;#39;...
OKAY [  1.571s]
finished. total time: 3.462s&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now you have ClockworkMod Recovery installed.&lt;/p&gt;

&lt;h2 id='step_3_install_the_virtuous_prime_rom'&gt;Step 3: Install the Virtuous Prime ROM&lt;/h2&gt;

&lt;p&gt;Following the instructions here will wipe everything on your tablet. And you will void your warranty - again. Proceed at your own risk.&lt;/p&gt;

&lt;p&gt;There are &lt;a href='http://rootzwiki.com/topic/21125-roms-series300312-virtuous-prime-94221-v1/'&gt;instructions on RootzWiki&lt;/a&gt; for installing Virtuous Prime. I&amp;#8217;m going to give you the same instructions but with a bit more detail. But I recommend reading the information on RootzWiki too as there is a lot of useful background there.&lt;/p&gt;

&lt;p&gt;Download the latest version of &lt;a href='http://www.virtuousrom.com/p/prime.html'&gt;Virtuous Prime&lt;/a&gt; directly onto your tablet. As of this writing that is Virtuous Prime 9.4.2.21 v1, which is based on the Transformer Prime v9.4.2.21 firmware from Asus. You will get a zip file - don&amp;#8217;t unzip it!&lt;/p&gt;

&lt;p&gt;Next to the download link there will be an MD5 checksum. We will refer back to that in a moment.&lt;/p&gt;

&lt;p&gt;Use your file manager to move the zip file, &lt;code&gt;virtuous_prime_s_9.4.2.21_v1.zip&lt;/code&gt; from &lt;code&gt;/sdcard/Download/&lt;/code&gt; to &lt;code&gt;/sdcard/&lt;/code&gt;. I think that this step is superfluous; but it makes me feel better.&lt;/p&gt;

&lt;p&gt;This is optional, but highly recommended: install the free &lt;a href='https://play.google.com/store/apps/details?id=com.fab.md5'&gt;MD5 Checker&lt;/a&gt; app. You can use this app to check the MD5 checksum of the file that you downloaded to make sure that it was not corrupted. Open MD5 Checker, click on the button labelled &amp;#8220;Load File 1&amp;#8221;, browse to the Virtuous Prime zip file, and wait for MD5 Checker to compute the file&amp;#8217;s checksum. Make sure that the checksum that you see in MD5 Checker is the same as the one from the Virtuous Prime downloads page. If the checksums do not match then do not proceed! Download the file again and check the checksum again.&lt;/p&gt;

&lt;p&gt;Shut down your tablet. But make sure that your battery is charged to at least 50% first. And make sure that the USB cable is unplugged.&lt;/p&gt;

&lt;p&gt;Boot into recovery mode by holding both the power and volume-down buttons. As with fastboot, when you see several lines of white text in the upper-left corner of the screen let go of both buttons. But this time press volume-up right away. If you do not press volume-up within five seconds then the tablet will go into fastboot. If that happens then just start over by holding the power and volume-down buttons again.&lt;/p&gt;

&lt;p&gt;After a moment you should see the ClockworkMod menu. You can use the volume-up and volume-down buttons to highlight the different menu options and the power button to select the option that you want.&lt;/p&gt;

&lt;p&gt;Make a backup of your current ROM. Select &amp;#8220;backup and restore&amp;#8221;, then &amp;#8220;backup&amp;#8221;. This will create a timestamped backup directory on your tablet under &lt;code&gt;/sdcard/clockwork/backup/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;There is a lot of information on backing up and restoring your tablet &lt;a href='http://www.androidpolice.com/2010/04/16/complete-guide-how-to-fully-back-up-and-restore-your-android-phone-using-nandroid-backup-and-clockworkmod-rom-manager/'&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The backup process will take a few minutes. When it is done you will see the ClockworkMod menu again.&lt;/p&gt;

&lt;p&gt;Select &amp;#8220;wipe data/factory reset&amp;#8221;. According to RootzWiki this step is optional, but is highly recommended. You will have to complete an elaborate confirmation step to start the wipe.&lt;/p&gt;

&lt;p&gt;Once all of your data has been wiped, select &amp;#8220;install zip from sdcard&amp;#8221;, then &amp;#8220;choose zip from sdcard&amp;#8221;. Browse to the Virtuous Prime ROM and select it. And confirm that you are really sure about this.&lt;/p&gt;

&lt;p&gt;You will be taken through a guided install process in which you will be prompted to choose between Typical, Complete, or Minimal install modes. There is a list of the differences between the three modes on &lt;a href='http://rootzwiki.com/topic/21125-roms-series300312-virtuous-prime-94221-v1/'&gt;RootzWiki&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;When the installer is finished your tablet will reboot and you are done! Congratulations! Enjoy your new ROM!&lt;/p&gt;

&lt;h2 id='more_resources'&gt;More Resources&lt;/h2&gt;

&lt;p&gt;There is some useful information collected on &lt;a href='http://transformerprimeroot.com/'&gt;TransformerPrimeRoot.com&lt;/a&gt;. Much of the information in my guide comes from that site.&lt;/p&gt;

&lt;p&gt;If the worst should happen and your tablet becomes a brick, you may still be able to recover. Check out the &lt;a href='http://forum.xda-developers.com/showthread.php?t=1514088'&gt;recovery guide&lt;/a&gt; on &lt;a href='http://forum.xda-developers.com/'&gt;XDA-Developers&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id='update_20120519'&gt;Update 2012-05-19&lt;/h2&gt;

&lt;p&gt;After about a week of use, the Virtuous Prime ROM is working very well. It does everything that the Asus firmware did and more. But I did run into some problems that I wanted to report along with some workarounds.&lt;/p&gt;

&lt;p&gt;The Hulu Plus app does not work for me anymore. When I try to play a video I get this message:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Streaming Unavailable [91]&lt;/p&gt;

&lt;p&gt;Sorry, we are unable to stream this video. Please check your Internet connection, ensure you have the latest official update for your device, and try again.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The Hulu app did work for me before I unlocked my tablet. There are &lt;a href='http://forum.xda-developers.com/showthread.php?t=1571405'&gt;reports that unlocking the bootloader is what causes this problem&lt;/a&gt;. This may not have anything to do with Virtuous Prime directly.&lt;/p&gt;

&lt;p&gt;A helpful community member created &lt;a href='http://forum.xda-developers.com/showthread.php?t=1449110'&gt;a modified version of the Hulu Plus app&lt;/a&gt; that does work. From the first post in that thread you can download and install the Landscape Mod HuluPlus.apk package. You will need to enable &amp;#8220;Unknown Sources&amp;#8221; to install the package. Before you install this version I suggest wiping the data of the original Hulu app and uninstalling it.&lt;/p&gt;

&lt;p&gt;The home view in the app is distorted; but the queue view works fine. This mod is based on a phone version of the original Hulu app rather than a tablet version. Video quality seems a bit low - I don&amp;#8217;t know whether that is due to my connection or to the app. With those caveats, the modified app works great for me.&lt;/p&gt;

&lt;p&gt;Netflix works perfectly. Hooray for Netflix!&lt;/p&gt;

&lt;p&gt;The Amazon Kindle app crashes when I try to open a book. I have tried wiping the app&amp;#8217;s data and reinstalling multiple times. I have also tried different books. And I have confirmed that I am running version 3.5.1.1, which is the latest version available in the Play Store right now.&lt;/p&gt;

&lt;p&gt;I managed to fix the Kindle app by following &lt;a href='http://forum.xda-developers.com/showthread.php?p=26109294#post26109294'&gt;instructions to fix Machinarium&lt;/a&gt;, which simply involves installing a missing font.&lt;/p&gt;

&lt;p&gt;An alternative workaround is to use the &lt;a href='https://read.amazon.com'&gt;Cloud Reader&lt;/a&gt;. Note that the Cloud Reader will work in &lt;a href='https://play.google.com/store/apps/details?id=com.android.chrome'&gt;Chrome for Android Beta&lt;/a&gt;, but will refuse to run in the default Android browser. You will not be able to install the extension that allows Cloud Reader to work offline since the mobile version of Chrome does not support extensions yet. So you will have to be connected to the internet to use the Cloud Reader.&lt;/p&gt;

&lt;p&gt;Someone on the XDA Developers forum asked whether the game Machinarium would install under Virtuous Prime. I tested this and found that the game will install - but it crashes on startup. I did not test this game before installing Virtuous Prime. All other games that I have tested have worked fine.&lt;/p&gt;

&lt;p&gt;It turns out that the problem with Machinarium is that there is a missing font in Virtuous Prime. Specifically the Droid Sans and Droid Sans Bold fonts are missing. There is &lt;a href='http://forum.xda-developers.com/showthread.php?p=26109294#post26109294'&gt;a fix&lt;/a&gt; reported in the XDA Developers forum.&lt;/p&gt;

&lt;p&gt;So with some digging it seems that I did not encounter any problems that I could not fix. Also, having root access to my tablet is excellent.&lt;/p&gt;</content>
 </entry>
 
 
 
 <entry>
   <title>Cookies are bad for you: Improving web application security</title>
   <link href="http://sitr.us/2011/08/26/cookies-are-bad-for-you.html" />
   <updated>2011-08-26T00:00:00-07:00</updated>
   <id>http://sitr.us/2011/08/26/cookies-are-bad-for-you</id>
   <content type="html">&lt;p&gt;Most web applications today use browser cookies to keep a user logged in while she is using the application. Cookies are a decades-old device and they do not stand up well to security threats that have emerged on the modern web. In particular, cookies are vulnerable to &lt;a href='http://en.wikipedia.org/wiki/Cross-site_request_forgery'&gt;cross-site request forgery&lt;/a&gt;. Web applications can by made more secure by using &lt;a href='http://oauth.net/'&gt;OAuth&lt;/a&gt; for session authentication.&lt;/p&gt;

&lt;p&gt;This post is based on &lt;a href='http://opensourcebridge.org/sessions/663'&gt;a talk that I gave&lt;/a&gt; at &lt;a href='http://opensourcebridge.org/'&gt;Open Source Bridge&lt;/a&gt; this year. The slides for that talk are available &lt;a href='/talks/cookies/'&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;img src='/talks/cookies/svg/cookies.svg' alt='cookie authentication' style='width: 100%' /&gt;
&lt;p&gt;When a user logs into a web application the application server sets a cookie value that is picked up by the user&amp;#8217;s browser. The browser includes the same cookie value in every request sent to the same host until the cookie expires. When the application server receives a request it can check whether the cookies attached to it contain a value that identifies a specific user. If such a cookie value exists then the server can consider the request to be authenticated.&lt;/p&gt;
&lt;img src='/talks/cookies/svg/cookie-strengths.svg' alt='attacks that target browser authentication' style='width: 100%' /&gt;
&lt;p&gt;There are many types of attacks that can be performed against a web application. Three that specifically target authentication between the browser and the server are &lt;a href='http://en.wikipedia.org/wiki/Man-in-the-middle_attack'&gt;man-in-the-middle (&lt;abbr title='man-in-the-middle'&gt;MITM&lt;/abbr&gt;)&lt;/a&gt;, &lt;a href='http://en.wikipedia.org/wiki/Cross-site_request_forgery'&gt;cross-site request forgery (&lt;abbr title='cross-site request forgery'&gt;CSRF&lt;/abbr&gt;)&lt;/a&gt;, and &lt;a href='http://en.wikipedia.org/wiki/Cross-site_scripting'&gt;cross-site scripting (&lt;abbr title='cross-site scripting'&gt;XSS&lt;/abbr&gt;)&lt;/a&gt;. Plain cookie authentication is vulnerable to all three.&lt;/p&gt;
&lt;img src='/talks/cookies/svg/session_hijacking.svg' alt='session hijacking' style='width: 100%' /&gt;
&lt;p&gt;In a &lt;abbr title='man-in-the-middle'&gt;MITM&lt;/abbr&gt; attack the attacker is in a position to watch traffic that passes between some user&amp;#8217;s browser and an application server. If that traffic is not encrypted the attacker could steal private information. One of the most dangerous things that an attacker can do in this position is to hijack the user&amp;#8217;s session by reading cookie data from an HTTP request and including that cookie data in the attacker&amp;#8217;s own requests to the same server. This is a form of privilege escalation attack. Using this technique an attacker can convince an application server that the attacker is actually the user who originally submitted a given cookie. Thus the attacker gains access to all of the user&amp;#8217;s protected resources.&lt;/p&gt;

&lt;p&gt;Last year a Firefox extension called &lt;a href='http://codebutler.com/firesheep'&gt;Firesheep&lt;/a&gt; made some waves when it was released. The purpose of Firesheep was to raise awareness of the danger of &lt;abbr title='man-in-the-middle'&gt;MITM&lt;/abbr&gt; attacks. Most web applications, at that time and today, use cookie authentication without an encrypted connection between browser and server. Firesheep makes it easy to spy on anybody who is using well known applications like Facebook and Twitter on a public network. With the click of a button you can perform a MITM attack yourself, steal someone&amp;#8217;s cookies, and gain access to that person&amp;#8217;s Facebook account.&lt;/p&gt;

&lt;p&gt;&lt;a href='http://en.wikipedia.org/wiki/Man-in-the-middle_attack'&gt;&lt;abbr title='man-in-the-middle'&gt;MITM&lt;/abbr&gt;&lt;/a&gt; attacks can be effectively blocked by using HTTPS to encrypt any traffic that contains sensitive information or authentication credentials. When using HTTPS you will almost certainly want to set the &amp;#8220;secure&amp;#8221; flag on any cookies used for authentication. That flag prevents the browser from transmitting cookies over an unencrypted connection.&lt;/p&gt;

&lt;p&gt;More and more web applications are offering HTTPS - often as on opt-in setting. Any web site that requires a login should offer HTTPS - and ideally it should be enabled by default.&lt;/p&gt;
&lt;img src='/talks/cookies/svg/xss.svg' alt='cross-site scripting' style='width: 100%' /&gt;
&lt;p&gt;&lt;a href='http://en.wikipedia.org/wiki/Cross-site_scripting'&gt;&lt;abbr title='cross-site scripting'&gt;XSS&lt;/abbr&gt;&lt;/a&gt; attacks involve an attacker pushing malicious JavaScript code into a web application. When another user visits a page with that malicious code in it the user&amp;#8217;s browser will execute the code. The browser has no way of telling the difference between legitimate and malicious code. Injected code is another mechanism that an attacker can use for session hijacking: by default cookies stored by the browser can be read by JavaScript code. The injected code can read a user&amp;#8217;s cookies and transmit those cookies to the attacker. Just like in the &lt;abbr title='man-in-the-middle'&gt;MITM&lt;/abbr&gt; scenario, the attacker can use those cookies to disguise herself as the hapless user.&lt;/p&gt;

&lt;p&gt;There are other ways that &lt;abbr title='cross-site scripting'&gt;XSS&lt;/abbr&gt; be used can be used to mess with a user - but session hijacking is probably the most dangerous. Session hijacking via XSS can be prevented by setting an &amp;#8220;httpOnly&amp;#8221; flag on cookies that are used for authentication. The browser will not allow JavaScript code to read or write any cookie that is flagged with &amp;#8220;httpOnly&amp;#8221;; but those cookies will still be transmitted in request headers.&lt;/p&gt;
&lt;img src='/talks/cookies/svg/csrf.svg' alt='cross-site request forgery' style='width: 100%' /&gt;
&lt;p&gt;&lt;a href='http://en.wikipedia.org/wiki/Cross-site_request_forgery'&gt;&lt;abbr title='cross-site request forgery'&gt;CSRF&lt;/abbr&gt;&lt;/a&gt; attacks authentication indirectly. A malicious web page can trick a browser into making cross-domain requests to another web site. If a user visiting the malicious page is already logged in to that web site then the malicious page can access the site resources as though it were logged in as the unsuspecting user. For example, if a malicious page can trick the browser into making POST requests to a microblogging site it can post updates with spam links that appear to have been written by the victim.&lt;/p&gt;

&lt;p&gt;If you use Facebook you might have encountered attacks like this yourself. You see a post on a friend&amp;#8217;s wall with a button that says &lt;a href='http://www.pcworld.com/businesscenter/article/182940/facebook_worm_spreads_with_a_lurid_lure.html'&gt;&amp;#8220;Don&amp;#8217;t click the button!&amp;#8221;&lt;/a&gt; When you click on it you are taken to another site and the same message ends up posted on your wall.&lt;/p&gt;

&lt;p&gt;This works because the browser automatically sends cookies set on a given domain with every request made to that domain, regardless of where those requests originated. The browser has no way of knowing that the requests initiated by the malicious page are made without the user&amp;#8217;s knowledge.&lt;/p&gt;

&lt;p&gt;The malicious page could create a cross-domain request by including an image with a &lt;code&gt;src&lt;/code&gt; attribute pointing to a &lt;abbr title='Uniform Resource Locator'&gt;URL&lt;/abbr&gt; on the site that it is trying to hack into. The URL does not have to be an image - the browser will make a GET request to that URL and will discard the response when it determines that the response is not image data. If that GET request produced any side-effects, like posting a microblogging update, then the malicious page has successfully performed an attack.&lt;/p&gt;

&lt;p&gt;To make a cross-domain POST request the malicious site might include a hidden HTML form with an &lt;code&gt;action&lt;/code&gt; attribute pointing at the site to be hacked. The malicious page can use JavaScript to submit the form without any interaction from the user. This is another case where the attacker cannot read the response that comes back but can trigger some action in the user&amp;#8217;s account.&lt;/p&gt;

&lt;p&gt;In some cases &lt;abbr title='cross-site request forgery'&gt;CSRF&lt;/abbr&gt; attacks can also be used to read data. Because &lt;abbr title='JavaScript Object Notation'&gt;JSON&lt;/abbr&gt; is a strict subset of JavaScript, &lt;a href='http://blog.archive.jpsykes.com/47/practical-csrf-and-json-security/'&gt;HTTP responses that contain &lt;abbr title='JavaScript Object Notation'&gt;JSON&lt;/abbr&gt; data can be loaded into script tags and executed.&lt;/a&gt; In some browsers a malicious page can override the Object and Array constructors to capture data from the &lt;abbr title='JavaScript Object Notation'&gt;JSON&lt;/abbr&gt; response as it is executed so that it can be sent to an attacker.&lt;/p&gt;

&lt;p&gt;The biggest problem with &lt;abbr title='cross-site request forgery'&gt;CSRF&lt;/abbr&gt; is that cookies provide absolutely no defense against this type of attack. If you are using cookie authentication you must also employ additional measures to protect against CSRF. The most basic precaution that you can take is to make sure that your application never performs any side-effects in response to GET requests.&lt;/p&gt;

&lt;p&gt;To protect against cross-domain POST requests a commonly used option is to use an &lt;a href='https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet#General_Recommendation:_Synchronizer_Token_Pattern'&gt;anti-forgery token&lt;/a&gt; that must be submitted with every POST, PUT, or DELETE request. The token is generally injected into the HTML code for forms in such a way that malicious code on another site does not have any way to access it.&lt;/p&gt;

&lt;p&gt;&lt;abbr title='JavaScript Object Notation'&gt;JSON&lt;/abbr&gt; responses can be protected by pre-pending the JSON response with some code that makes the response non-executable. For example, you could place a JavaScript loop at the beginning of the response that never terminates. Or you could put in a statement that throws an exception. Putting the whole JSON response inside of a comment block also works. The only way for a browser to read JSON data that has been obfuscated like this is to fetch the resource using &lt;abbr title='XMLHttpRequest'&gt;XHR&lt;/abbr&gt; and to remove the extra code before parsing the actual &lt;abbr title='JavaScript Object Notation'&gt;JSON&lt;/abbr&gt; data. XHR is limited by the &lt;a href='http://en.wikipedia.org/wiki/Same_origin_policy'&gt;same-origin policy&lt;/a&gt;; so a malicious page cannot make a cross-site &lt;abbr title='XMLHttpRequest'&gt;XHR&lt;/abbr&gt; request.&lt;/p&gt;

&lt;p&gt;Such multi-layered approaches to &lt;abbr title='cross-site request forgery'&gt;CSRF&lt;/abbr&gt; defense work but are a pain to implement. I know from experience that the stateful nature of anti-forgery tokens make them a constant source of bugs in Ajax-driven applications where users might submit several requests to the server without ever loading a new page. It is too easy for the client and server to get out of sync and to disagree about which anti-forgery tokens are fresh. And great care must be taken to include the anti-forgery feature in every form and Ajax call in an application or a security hole appears.&lt;/p&gt;

&lt;p&gt;&lt;abbr title='JavaScript Object Notation'&gt;JSON&lt;/abbr&gt; obfuscation is easier to apply to every JSON response as a blanket policy thanks to server-side filters and client-side hooks, such as those in jQuery&amp;#8217;s Ajax stack. But then you are not really serving &lt;abbr title='JavaScript Object Notation'&gt;JSON&lt;/abbr&gt; - you are serving a JSON-like type with a proprietary wrapper. I find that I spend a lot of time instructing people on the existence of obfuscation, explaining why it is there, and explaining how to set up hooks to remove it on the client side.&lt;/p&gt;
&lt;img src='/talks/cookies/svg/secure-cookie-plus-https-strengths.svg' alt='protections provided by the &amp;quot;httpOnly&amp;quot; and &amp;quot;secure&amp;quot; flags' style='width: 100%' /&gt;
&lt;p&gt;By combining the &amp;#8220;secure&amp;#8221; and &amp;#8220;httpOnly&amp;#8221; flags and using HTTPS you can make your application authentication proof against &lt;abbr title='man-in-the-middle'&gt;MITM&lt;/abbr&gt; attacks and against some &lt;abbr title='cross-site scripting'&gt;XSS&lt;/abbr&gt; attacks. But there is nothing that will make cookie authentication resistant to &lt;abbr title='cross-site request forgery'&gt;CSRF&lt;/abbr&gt; attacks. The only way to protect against CSRF is to apply additional security measures. Often multiple measures are required to combat different possible CSRF vectors. And those measures are not always simple or transparent.&lt;/p&gt;

&lt;p&gt;In my opinion &lt;abbr title='cross-site request forgery'&gt;CSRF&lt;/abbr&gt; stifles innovation on the web. Because cross-domain requests cannot be trusted, even if they appear to be authenticated, web applications have to be thoroughly locked down to reject any cross-origin traffic. There is a relatively new specification for making cross-origin &lt;abbr title='XMLHttpRequest'&gt;XHR&lt;/abbr&gt; requests called &lt;a href='http://www.w3.org/TR/cors/'&gt;Cross-Origin Resource Sharing (&lt;abbr title='Cross-Origin Resource Sharing'&gt;CORS&lt;/abbr&gt;)&lt;/a&gt;. This specification could allow for exciting new mashups involving rich JavaScript applications and public APIs. Most modern browsers support &lt;abbr title='Cross-Origin Resource Sharing'&gt;CORS&lt;/abbr&gt; too - including Internet Explorer 8. But CORS is rarely used because it opens up a big hole that could be exploited by &lt;abbr title='cross-site request forgery'&gt;CSRF&lt;/abbr&gt;. Existing CSRF countermeasures rely on limiting &lt;abbr title='XMLHttpRequest'&gt;XHR&lt;/abbr&gt; requests to the same-origin policy. For most web developers the risk is too great to justify experimenting with new technology.&lt;/p&gt;

&lt;p&gt;The way to make the web a safer place is to switch to authentication mechanisms that provide strong protection against &lt;abbr title='cross-site request forgery'&gt;CSRF&lt;/abbr&gt; at the most basic level. The key is to choose a mechanism that is controlled by the web application, not the browser. The web browser has no way of distinguishing legitimate requests from forged ones - it will attach cookies to both. On the other hand, application code can be written to be smarter.&lt;/p&gt;
&lt;img src='/talks/cookies/svg/Oauth_logo.svg' alt='OAuth' style='width: 50%; display: block; margin-left: auto; margin-right: auto;' /&gt;
&lt;p&gt;There are many authentication schemes that would work well. I lean toward OAuth 2.0. OAuth has some nice advantages: it is standardized; there are numerous server implementations; and the simplest form of the &lt;a href='http://tools.ietf.org/html/draft-ietf-oauth-v2-20'&gt;OAuth 2.0 draft specification&lt;/a&gt; is pretty easy to implement.&lt;/p&gt;
&lt;img src='/talks/cookies/svg/oauth_auth_code_step_1.svg' alt='three-legged OAuth' style='width: 100%' /&gt;
&lt;p&gt;In a traditional OAuth setup there are three parties: the authorization server / resource server, the client and the resource owner. Through a series of steps the resource owner, typically a user working through a web browser, submits a password to the authorization server and the authorization server issues an access token to the client. You can read more about the OAuth protocol flow on the &lt;a href='http://oauth.net/2/'&gt;OAuth 2.0 web site&lt;/a&gt;.&lt;/p&gt;
&lt;img src='/talks/cookies/svg/oauth_auth_pass_step_1.svg' alt='two-legged OAuth' style='width: 100%' /&gt;
&lt;p&gt;When applying OAuth to session authentication the picture becomes simpler: the browser acts as both the resource owner and the client; so some of the indirection of three-legged OAuth can be skipped. Instead, a web application can use a protocol flow that the OAuth 2.0 specification calls &lt;a href='http://tools.ietf.org/html/draft-ietf-oauth-v2-20#section-4.3'&gt;Resource Owner Password Credentials&lt;/a&gt; in which the user enters her password into a login form, the password is submitted to the application server directly, and the server responds to that request with an access token. You can think of this as &amp;#8220;two-legged&amp;#8221; OAuth.&lt;/p&gt;
&lt;img src='/talks/cookies/svg/oauth_auth_pass_step_3.svg' alt='a request signed with OAuth' style='width: 100%' /&gt;
&lt;p&gt;In both the two- and three-legged flows requests are signed by adding an &amp;#8220;Authorization&amp;#8221; header with one of two possible formats. In the &lt;a href='http://tools.ietf.org/html/draft-ietf-oauth-v2-bearer-06'&gt;bearer scheme&lt;/a&gt; the authorization header value is just the access token that was given to the client. For example:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;GET /resource HTTP/1.1
Host: server.example.com
Authorization: Bearer vF9dft4qmT&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;a href='http://tools.ietf.org/html/draft-ietf-oauth-v2-http-mac-00'&gt;HMAC scheme&lt;/a&gt; is a bit more complicated: in that case the client is given an access token id in addition to the token itself and the authorization header includes the token id and an HMAC-signed hash of the request &lt;abbr title='Uniform Resource Locator'&gt;URL&lt;/abbr&gt;, the request method, a nonce, and possibly a nested hash of the request body. The OAuth access token is used as the key in the &lt;a href='http://en.wikipedia.org/wiki/HMAC'&gt;HMAC algorithm&lt;/a&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;POST /request HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
Authorization: MAC id=&amp;quot;jd93dh9dh39D&amp;quot;,
             nonce=&amp;quot;273156:di3hvdf8&amp;quot;,
             bodyhash=&amp;quot;k9kbtCly0Cly0Ckl3/FEfpS/olDjk6k=&amp;quot;,
             mac=&amp;quot;W7bdMZbv9UWOTadASIQHagZyirA=&amp;quot;

hello=world%21&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The advantage of the HMAC scheme is that it can provide some protection against &lt;abbr title='man-in-the-middle'&gt;MITM&lt;/abbr&gt; attacks even if signed requests are not encrypted with HTTPS.&lt;/p&gt;

&lt;p&gt;I propose a design in which the browser submits credentials from a login form to the server via &lt;abbr title='XMLHttpRequest'&gt;XHR&lt;/abbr&gt;, gets an access token back, and uses that access token to sign subsequent requests. Full page requests and form posts are difficult to sign with OAuth - hyperlinks and form tags do not provide a way to specify an &amp;#8220;Authorization&amp;#8221; header. So OAuth-signed requests would probably be limited to &lt;abbr title='XMLHttpRequest'&gt;XHR&lt;/abbr&gt;. The browser could store the OAuth access token in a persistent client-side store to give the user an experience that is indistinguishable from a cookie-based application - but that is more secure.&lt;/p&gt;

&lt;p&gt;It is entirely possible for JavaScript code running in a web browser to sign requests with HMAC. There are pure JavaScript implementations available of many cryptographic functions, including &lt;a href='http://jssha.sourceforge.net/'&gt;SHA-1 and SHA-256&lt;/a&gt;, which are the hash functions that are used for OAuth HMAC signing. However, if your application uses HTTPS to protect every request then the simpler bearer scheme is entirely sufficient.&lt;/p&gt;

&lt;p&gt;In this design form posts would be eliminated. Instead form data would be serialized in JavaScript and submitted using Ajax. That way all requests that produce side-effects would be channeled through OAuth-signed &lt;abbr title='XMLHttpRequest'&gt;XHR&lt;/abbr&gt;. I am not suggesting eliminating form tags though - form tags are an essential tool for semantic markup and for accessibility. I recommend that JavaScript be used to intercept form &amp;#8220;submit&amp;#8221; events.&lt;/p&gt;
&lt;img src='/talks/cookies/svg/bigpipe_step_1.svg' alt='the BigPipe design' style='width: 100%' /&gt;
&lt;p&gt;There are a couple of options for dealing with full page loads. One possibility is to not require any authentication for requests for HTML pages and to design your application so that HTML responses do not include any protected information. Such an application would serve pages as skeletons, with empty areas that to be filled in with dynamic and protected content after page load using Ajax. The dynamic responses could be HTML fragments that are protected by OAuth, or they could be &lt;abbr title='JavaScript Object Notation'&gt;JSON&lt;/abbr&gt; responses that are rendered as HTML using client-side templates.&lt;/p&gt;

&lt;p&gt;Facebook uses a process like this which they call &lt;a href='https://www.facebook.com/notes/facebook-engineering/bigpipe-pipelining-web-pages-for-high-performance/389414033919'&gt;BigPipe&lt;/a&gt;. Facebook&amp;#8217;s rationale for BigPipe is actually performance, not security. In my opinion the BigPipe approach gives a best-of-both-worlds blend of performance and security. Plus, it lets you put caching headers on full page responses, even in apps with lots of dynamic content.&lt;/p&gt;

&lt;p&gt;A downside of BigPipe is that content that is loaded via Ajax generally cannot be indexed by search engines. Google&amp;#8217;s recently published specification for &lt;a href='http://code.google.com/web/ajaxcrawling/'&gt;making Ajax applications crawlable&lt;/a&gt; may provide a solution to that problem. Or you might choose to use the BigPipe approach everywhere in your application except for publicly accessible pieces of content.&lt;/p&gt;

&lt;p&gt;Another way to handle full page loads would be to continue using cookie authentication for HTML resources. HTML responses are less vulnerable to &lt;abbr title='cross-site request forgery'&gt;CSRF&lt;/abbr&gt; snooping than &lt;abbr title='JavaScript Object Notation'&gt;JSON&lt;/abbr&gt; because HTML is not executable in script tags. In this case you should still require OAuth signing on requests for JSON resources and on any requests that could produce side-effects. But allowing cookie authentication on non-side-effect-producing GET requests for HTML resources should be safe.&lt;/p&gt;
&lt;img src='/talks/cookies/svg/oauth-plus-https-strengths.svg' alt='strengths of OAuth' style='width: 100%' /&gt;
&lt;p&gt;Using JavaScript to manage access tokens rather than relying on a built-in browser function makes &lt;abbr title='cross-site request forgery'&gt;CSRF&lt;/abbr&gt; attacks impractical. A malicious third-party site can no longer rely on browsers to automatically attach authentication credentials to requests that it triggers. Client-side storage implementations are generally protected by the &lt;a href='http://en.wikipedia.org/wiki/Same_origin_policy'&gt;same origin policy&lt;/a&gt; - so only code running in your application can retrieve an access token and produce an authenticated request. And if you combine OAuth with HTTPS then you are also protected against &lt;abbr title='man-in-the-middle'&gt;MITM&lt;/abbr&gt; attacks.&lt;/p&gt;

&lt;p&gt;A drawback is that you lose the &lt;abbr title='cross-site scripting'&gt;XSS&lt;/abbr&gt; protection that the &amp;#8220;httpOnly&amp;#8221; cookie flag provides with cookie authentication. An application that uses OAuth will have to use other methods to block &lt;abbr title='cross-site scripting'&gt;XSS&lt;/abbr&gt;. But in my opinion there are better options for dealing with XSS than there are for dealing with &lt;abbr title='cross-site request forgery'&gt;CSRF&lt;/abbr&gt;. By consistently sanitizing user-generated content you can effectively block XSS at the presentation layer of your application. That would be necessary anyway, since &amp;#8220;httpOnly&amp;#8221; only prevents &lt;abbr title='cross-site scripting'&gt;XSS&lt;/abbr&gt;-based privilege escalation attacks and by itself does not prevent other XSS shenanigans.&lt;/p&gt;

&lt;p&gt;To track a session using OAuth applications will need some way to store access tokens for the duration of a user&amp;#8217;s session. There are various ways to do that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;In the simplest case you can store the token in memory by assigning it to a JavaScript variable. This might be useful in a single page application. The user will have to log in again if she goes to another page or opens your app in a new window.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;&lt;a href='https://developer.mozilla.org/en/dom/storage#localStorage'&gt;localStorage&lt;/a&gt; can be used to store a token so that is persistent even if the user closes and re-opens the browser. Data stored in localStorage is available to all windows on the same domain. You will probably want to include a hook to clear local storage when the user logs out of your application.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;&lt;a href='https://developer.mozilla.org/en/dom/storage#sessionStorage'&gt;sessionStorage&lt;/a&gt; works like localStorage, except that data is only accessible from the same window that stored it and the whole store for a given window is wiped when the user closes that window. So the user does not have to log in again if she goes to another page; but she does have to log in again if she opens your app in a new window.&lt;/p&gt;

&lt;p&gt;sessionStorage can be a more secure option than localStorage - especially on a shared or a public computer. If you decide to use a storage option that does not expire automatically when the browser is closed I suggest including a &amp;#8220;remember me&amp;#8221; checkbox in your login form and using sessionStorage instead when the user does not check that box.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Although I have been arguing that cookies are not the best option for authentication, storing an access token in a cookie works just fine. The key is that the server should not consider the cookie to be sufficient for authentication. Instead it should require that the access token be copied from the cookie value into an OAuth header.&lt;/p&gt;

&lt;p&gt;For the cookie option to be secure you should set the &amp;#8220;secure&amp;#8221; flag so that it is not transmitted over a connection that could be read via a &lt;abbr title='man-in-the-middle'&gt;MITM&lt;/abbr&gt; attack. You should not set the &amp;#8220;httpOnly&amp;#8221; flag because the cookie needs to be accessible from JavaScript.&lt;/p&gt;

&lt;p&gt;A nice advantage of the cookie option is that users have been trained that they can delete cookies to reset a session. On the other hand, most users do not know about localStorage and most browsers do not provide an obvious way to clear localStorage. So the cookie option is likely to conform best to user expectations. Cookies can also be configured to expire when the browser is closed or to persist for a long period of time.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;p&gt;Other options include &lt;a href='https://developer.mozilla.org/en/IndexedDB'&gt;IndexedDB&lt;/a&gt;, which is a more sophisticated store that is similar to localStorage, &lt;a href='http://en.wikipedia.org/wiki/Flash_cookies'&gt;Flash cookies&lt;/a&gt;, and &lt;a href='http://msdn.microsoft.com/en-us/library/ms531424(v=vs.85).aspx'&gt;userData&lt;/a&gt; in IE.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is a good summary of client-side storage implementations and how to use them on &lt;a href='http://diveintohtml5.info/storage.html'&gt;Dive Into HTML5&lt;/a&gt;. Or if you want a pre-built solution that avoids most cross-browser headaches you can use &lt;a href='http://pablotron.org/software/persist-js/'&gt;PersistJS&lt;/a&gt; or a similar tool.&lt;/p&gt;

&lt;p&gt;Web applications that rely on cookie authentication can often be designed to degrade gracefully, so that if JavaScript is disabled or is not available the application will still work. With OAuth that is not possible. I can imagine this being a major objection to ditching cookie authentication. Some people prefer to disable JavaScript for security or for privacy reasons. Many of the more basic mobile and text-only web browsers do not support JavaScript. And in the past screen readers have not handled JavaScript-driven web apps well.&lt;/p&gt;

&lt;p&gt;In my opinion the requirement that JavaScript be enabled to use an application is generally worthwhile. Mobile browsers that do support JavaScript are rapidly pushing out those that do not. Text-only browsers will have to start supporting JavaScript sooner or later to keep up. The people who designed your web browser took great care to ensure that your security and privacy are protected even when JavaScript is enabled. Screen readers are much better than they used to be at making JavaScript-driven web sites accessible.&lt;/p&gt;

&lt;p&gt;You should consider your target audience, your application requirements, and your security needs and decide for yourself whether dropping the noscript option is the right choice for your application.&lt;/p&gt;

&lt;p&gt;No security protocol is bulletproof. Do lots of research and use common sense whenever you are working on an application that needs to be secure.&lt;/p&gt;

&lt;p&gt;Image credits:&lt;/p&gt;

&lt;p&gt;The &lt;a href='http://en.wikipedia.org/wiki/File:Oauth_logo.svg'&gt;OAuth logo&lt;/a&gt; by Chris Messina is licensed under the &lt;a href='http://en.wikipedia.org/wiki/en:Creative_Commons'&gt;Creative Commons&lt;/a&gt; &lt;a href='http://creativecommons.org/licenses/by-sa/3.0/deed.en'&gt;Attribution-Share Alike 3.0 Unported&lt;/a&gt; license.&lt;/p&gt;

&lt;p&gt;Other images used in diagrams are from the &lt;a href='http://en.wikipedia.org/wiki/Open_Clip_Art_Library'&gt;Open Clip Art Library&lt;/a&gt; and are in the public domain.&lt;/p&gt;

&lt;p&gt;tags: osb11&lt;/p&gt;</content>
 </entry>
 
 
 
 <entry>
   <title>How Mobile Safari emulates mouse events</title>
   <link href="http://sitr.us/2011/07/28/how-mobile-safari-emulates-mouse-events.html" />
   <updated>2011-07-28T00:00:00-07:00</updated>
   <id>http://sitr.us/2011/07/28/how-mobile-safari-emulates-mouse-events</id>
   <content type="html">&lt;p&gt;When you are adapting web apps to touchscreen devices particular challenges come up around events like &lt;code&gt;mouseover&lt;/code&gt; and &lt;code&gt;mouseout&lt;/code&gt;. Touchscreen devices like the iPad do not have a cursor, so the user cannot exactly move the mouse over an HTML element. However, Mobile Safari, the web browser that comes with the iPhone and iPad, has a fallback for websites that require hovering or cursor movement.&lt;/p&gt;

&lt;p&gt;Usually when you tap on an element on a link or other clickable element Mobile Safari translates that into a regular &lt;code&gt;click&lt;/code&gt; event. The browser also produces some touch events that do not exist in a lot of browsers. But from the perspective of a web page that was not designed with a touchscreen in mind, what you get is a plain &lt;code&gt;click&lt;/code&gt;. More specifically, the browser fires &lt;code&gt;mousedown&lt;/code&gt;, &lt;code&gt;mouseup&lt;/code&gt;, and &lt;code&gt;click&lt;/code&gt; in that order. But if a clickable element also does something on &lt;code&gt;mouseover&lt;/code&gt; then tapping on that element will trigger a &lt;code&gt;mouseover&lt;/code&gt; event instead of a &lt;code&gt;click&lt;/code&gt;. Tapping on the same element again will produce a &lt;code&gt;click&lt;/code&gt; event. A random example of a page that exhibits this behavior is &lt;a href='http://opensourcebridge.org/events/2011/schedule'&gt;the schedule page&lt;/a&gt; from the &lt;a href='http://opensourcebridge.org/'&gt;Open Source Bridge&lt;/a&gt; website. Try tapping on session titles and see what happens.&lt;/p&gt;

&lt;p&gt;Mobile Safari will only produce mouse events when the user taps on a clickable element, like a link. You can make an element clickable by adding an onClick event handler to it, even if that handler does nothing. On tap Mobile Safari fires the events &lt;code&gt;mouseover&lt;/code&gt;, &lt;code&gt;mousemove&lt;/code&gt;, &lt;code&gt;mousedown&lt;/code&gt;, &lt;code&gt;mouseup&lt;/code&gt;, and &lt;code&gt;click&lt;/code&gt; in that order - with some caveats which are explained below. Those events all fire together after the user lifts her finger. You might expect the &lt;code&gt;mousedown&lt;/code&gt; event to fire as soon as the user presses her finger to the screen - but it does not. When the user taps on another clickable element the browser fires a &lt;code&gt;mouseout&lt;/code&gt; event on the first element in addition to firing the aforementioned events on the new element.&lt;/p&gt;

&lt;p&gt;So how do we get to the behavior where one tap emulates &lt;code&gt;mouseover&lt;/code&gt; and a second tap emulates &lt;code&gt;click&lt;/code&gt;? It turns out that after any &lt;code&gt;mouseover&lt;/code&gt; event handlers run Safari checks the DOM for changes and if the content has changed it skips the &lt;code&gt;mousedown&lt;/code&gt;, &lt;code&gt;mouseup&lt;/code&gt;, and &lt;code&gt;click&lt;/code&gt; events. So these events do not fire. When the user taps on the same element again the &lt;code&gt;mouseover&lt;/code&gt; event does not fire again, so the browser goes ahead with the other events.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;mousemove&lt;/code&gt; event behaves in a similar way: if the DOM has changed after any &lt;code&gt;mousemove&lt;/code&gt; handlers are finished running then Mobile Safari skips the remaining events.&lt;/p&gt;
&lt;figure&gt;
  &lt;figcaption&gt;
    Diagram from &lt;a href='http://developer.apple.com/library/safari/#documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html'&gt;Apple's
    documentation&lt;/a&gt; demonstrating how the browser determines which
    mouse events to fire.
  &lt;/figcaption&gt;
  &lt;img src='/images/events_1_finger.jpg' alt='mouse event firing diagram' /&gt;
&lt;/figure&gt;
&lt;p&gt;Safari does not accept just any change to a DOM element as a &amp;#8220;content change&amp;#8221; though. Through testing I discovered that adding a regular element to the DOM or showing a previously hidden element in a &lt;code&gt;mouseover&lt;/code&gt; handler would prevent the &lt;code&gt;click&lt;/code&gt; event from firing. But removing an element, hiding an element, or changing the content of a text node do not prevent the &lt;code&gt;click&lt;/code&gt; event. I also tried adding class names to elements - which Safari also did not treat as a &amp;#8220;content change&amp;#8221;. As far as I can tell only adding or showing an element will cause the &lt;code&gt;mousedown&lt;/code&gt;, &lt;code&gt;mouseup&lt;/code&gt;, and &lt;code&gt;click&lt;/code&gt; events to be skipped.&lt;/p&gt;

&lt;p&gt;I created some fiddles on &lt;a href='http://jsfiddle.net/'&gt;jsfiddle.net&lt;/a&gt; to test Mobile Safari behavior. For your investigative pleasure I have &lt;a href='http://jsfiddle.net/hallettj/pgpLA/'&gt;an example of a &lt;code&gt;mouseover&lt;/code&gt; handler that adds elements to the DOM&lt;/a&gt;, &lt;a href='http://jsfiddle.net/hallettj/4wjgk/'&gt;another that shows a hidden element&lt;/a&gt;, and &lt;a href='http://jsfiddle.net/hallettj/m5EXk/'&gt;a third that makes no changes to the DOM at all&lt;/a&gt;.&lt;/p&gt;</content>
 </entry>
 
 
 
 <entry>
   <title>CouchDB Notes</title>
   <link href="http://sitr.us/2009/09/13/couchdb-notes.html" />
   <updated>2009-09-13T00:00:00-07:00</updated>
   <id>http://sitr.us/2009/09/13/couchdb-notes</id>
   <content type="html">&lt;p&gt;Recently I gave a talk at &lt;a href='http://pdxruby.org/' title='Portland Ruby Brigade'&gt;Portland Ruby Brigade&lt;/a&gt; meeting on &lt;a href='http://couchdb.apache.org/' title='CouchDB'&gt;CouchDB&lt;/a&gt;, a document-oriented database. I thought I would share my notes from that talk. In some respects this was a followup to &lt;a href='http://groups.google.com/group/pdxruby/browse_thread/thread/6f8734846d3e16d3' title='Comparing MongoDB, Tokyo Tyrant, and CouchDB'&gt;an earlier talk that Igal Koshevoy gave comparing various post-relational databases&lt;/a&gt;. Igal also wrote &lt;a href='http://groups.google.com/group/pdxruby/browse_thread/thread/7865318fbc65d0d1' title='Ruby Persistence with CouchDB'&gt;some additional notes on my talk&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In summary, some of the distinguishing features of CouchDB are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Schema-less data store stores documents containing arbitrary JSON data.&lt;/li&gt;

&lt;li&gt;Incrementally updated map-reduce views provide fast access to data, support powerful data processing, and eliminate lookup penalties for data in large or deeply nested documents.&lt;/li&gt;

&lt;li&gt;Map-reduce views - which are again, incrementally updated - provide fast access to aggregate data, such as sums or averages of document attributes.&lt;/li&gt;

&lt;li&gt;Schema-less design means no schema migrations are ever required. And new map-reduce views can be installed with no downtime.&lt;/li&gt;

&lt;li&gt;&amp;#8220;Crash-only&amp;#8221; design protects data integrity in almost every crash scenario. No recovery process is required when rebooting a crashed database server.&lt;/li&gt;

&lt;li&gt;Lock-free design means that read requests never have to wait for other read or write requests to finish. Writes are only serialized at the point where data is actually written to the disk.&lt;/li&gt;

&lt;li&gt;Integrated, robust master-master replication with automatic conflict handling&lt;/li&gt;

&lt;li&gt;MVCC, or &amp;#8220;optimistic locking&amp;#8221;, prevents data loss from multiple writes to the same document from different sources.&lt;/li&gt;

&lt;li&gt;RESTful interface makes it easy to integrate CouchDB with any environment that speaks HTTP.&lt;/li&gt;

&lt;li&gt;Documents can contain binary attachments. Attachment support combined with the HTTP interface means that CouchDB can serve HTML, JavaScript, images, and anything else required to host a web application directly from the database.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More detailed information on all of the above points can be found in &lt;a href='http://couchdb.apache.org/docs/overview.html' title='CouchDB Technical Overview'&gt;CouchDB&amp;#8217;s technical overview&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Some of the downsides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Writes and single-document lookups are slower than other databases due to HTTP overhead and frequent disk access.&lt;/li&gt;

&lt;li&gt;CouchDB optimizes CPU and RAM use by using lots of disk space. The same data set will take up a lot more space in CouchDB than in other database systems.&lt;/li&gt;

&lt;li&gt;You must create map-reduce views in advance for any queries you want to run. SQL users are used to processing data at query time; but this is not allowed by the CouchDB design (assuming you are not using temporary views in production, which you should not do.)&lt;/li&gt;

&lt;li&gt;There is a serious learning curve when learning to think in terms of map-reduce views.&lt;/li&gt;

&lt;li&gt;Map-reduce views, though very powerful, are not as flexible as SQL queries. There may be cases where it is necessary to push data processing to an asynchronous job or to the client.&lt;/li&gt;

&lt;li&gt;CouchDB is a young project and its API is undergoing rapid changes.&lt;/li&gt;

&lt;li&gt;Documentation can be sparse - especially when very new features are involved.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id='ruby_interfaces_to_couchdb'&gt;Ruby Interfaces to CouchDB&lt;/h2&gt;

&lt;p&gt;I also talked about some of the high-level interfaces to CouchDB that are available for Ruby. As ActiveRecord did for SQL, the idea behind these libraries is to abstract away as much of the database behavior as possible without sacrificing the powerful features that CouchDB provides. The term &amp;#8220;ORM&amp;#8221; does not quite apply to CouchDB because it is not relational. The term I am using for the time being is &amp;#8220;object-document mapping&amp;#8221;. The code examples I showed are all available in &lt;a href='http://gist.github.com/161472' title='ODM Code Examples'&gt;a gist&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Sadly I don&amp;#8217;t think I can say that any of these libraries are production ready as is. If you use one expect to write some patches as you go. That said I think that all three show some exciting potential. And they all provide a better starting point for your CouchDB project than writing your own ODM or using a low-level interface. I plan to submit a few patches to CouchPotato as I get to know it better. With some more help I imagine we can turn one or more of these interfaces into a nicely polished library.&lt;/p&gt;

&lt;p&gt;The winner in my mind is &lt;a href='http://upstream-berlin.com/2008/10/27/couch-potato-unleashed-a-couchdb-persistence-layer-in-ruby/' title='CouchPotato'&gt;CouchPotato&lt;/a&gt;. The philosophy behind CouchPotato is to do things differently than ActiveRecord does. Though it does borrow features from ActiveRecord, for example dirty attribute tracking, life cycle callbacks, and validations. The biggest innovation in CouchPotato in my opinion is the extensible system for defining views. As with the other libraries, support for declaring simple views is built in:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class User
    include CouchPotato::Persistence
    property :name
    view :by_name, :key =&amp;gt; :name
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But similar shortcuts for more sophisticated types of views can be added by creating new view classes and passing a &lt;code&gt;:type&lt;/code&gt; option to the &lt;code&gt;view&lt;/code&gt; declaration method. For example, it might be possible to declare views like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class Invoice
    ...
    property :ordered_at, :type =&amp;gt; Time
    property :items
    view(:total_sales, :type =&amp;gt; :aggregate, :key =&amp;gt; :ordered_at,
         :sum =&amp;gt; &amp;#39;items[].qty * items[].price_per_unit&amp;#39;)
    view(:average_sale, :type =&amp;gt; :aggregate, :key =&amp;gt; :ordered_at,
         :average =&amp;gt; &amp;#39;items[].qty * items[].price_per_unit&amp;#39;)
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;My runner-up is &lt;a href='http://github.com/jchris/couchrest' title='CouchRest'&gt;CouchRest&lt;/a&gt;. CouchRest is a widely used low-level interface to CouchDB. But it also includes a high-level interface called CouchRest::ExtendedDocument. A neat feature of this library is that you can declare a different database to use for each model. It also supports declaring simple views with dynamic methods for querying those views:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class Comment &amp;lt; CouchRest::ExtendedDocument
    property :post_id
    view_by :post_id
end

Comment.by_post_id :key =&amp;gt; &amp;#39;foo&amp;#39;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;a href='http://github.com/georgepalmer/couch_foo' title='CouchFoo'&gt;CouchFoo&lt;/a&gt; is another strong contender. The goal of CouchFoo is to provide an API that is as close to ActiveRecord&amp;#8217;s as possible. The project may even be porting a large amount of ActiveRecord code for this purpose. The intention is to make migrating to CouchDB as painless as possible.&lt;/p&gt;

&lt;p&gt;An interesting feature is that CouchFoo will create views automatically on demand. For example this query will automatically create a view that indexes Post documents by title:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;post = Post.find(:first, :conditions =&amp;gt; { :title =&amp;gt; &amp;quot;First Post&amp;quot; })&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;On-demand view creation could be convenient. But my instinct is that it is a bad thing to do. Adding a new view to a large database comes with an expensive initial build step. It seems to me that that type of thing should only be done explicitly.&lt;/p&gt;

&lt;h2 id='testimonials'&gt;Testimonials&lt;/h2&gt;

&lt;p&gt;I mentioned a case where one team found that they got great performance improvements by pushing some data reporting tasks from a SQL database to CouchDB. That story was written up in a series of blog posts. An explanation of why this team went with CouchDB is presented in &lt;a href='http://johnpwood.net/2009/07/10/couchdb-views-%E2%80%93-the-advantages/' title='CouchDB: Views - The Advantages'&gt;part 3 of that series&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There is &lt;a href='http://wiki.apache.org/couchdb/CouchDB_in_the_wild' title='Sites using CouchDB in production'&gt;a list on the CouchDB Wiki of sites that are currently using CouchDB in production&lt;/a&gt;. A couple of notable examples not on the list that have used CouchDB are the &lt;a href='http://www.erlang-factory.com/conference/London2009/speakers/endafarrell' title='The BBC on CouchDB'&gt;BBC&lt;/a&gt; and possibly &lt;a href='http://code.google.com/p/couchdb-lounge/' title='CouchDB Lounge'&gt;Meebo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Of note for Ubuntu fans: Canonical is working on a project called &lt;a href='http://www.kryogenix.org/days/2009/09/03/desktop-couch-irc-talk' title='Desktop Couch'&gt;Desktop Couch&lt;/a&gt; which will be installed by default in Karmic Koala. The idea is to create a portable store for stuff like browser bookmarks, contacts, music playlists and ratings, and so on. There are already plugins to allow Firefox and Evolution to store &lt;a href='http://www.kryogenix.org/days/2009/07/06/firefox-bookmarks-in-couchdb' title='Firefox and CouchDB'&gt;bookmarks&lt;/a&gt; and &lt;a href='http://blogs.gnome.org/rodrigo/2009/06/19/couchdb-contacts-in-evolution' title='Evolution and CouchDB'&gt;contact data&lt;/a&gt; in CouchDB. Desktop Couch will provide CouchDB databases for every user to store this information, and will include tools for &amp;#8220;pairing&amp;#8221; computers on the same network. Desktop Couch will use CouchDB&amp;#8217;s built-in replication features to automatically replicate data between paired computers; so you will get the same bookmarks and contacts on all of your computers. This will all integrate with &lt;a href='https://ubuntuone.com/' title='Ubuntu One'&gt;Ubuntu One&lt;/a&gt; too. Desktop Couch will be able to replicate your data to Ubuntu One&amp;#8217;s servers so that you can replicate that data back down to computers on a different network.&lt;/p&gt;

&lt;h2 id='exploring_further'&gt;Exploring Further&lt;/h2&gt;

&lt;p&gt;The best resource for learning more about CouchDB is probably CouchDB: The Definitive Guide. This is a book that J. Chris Anderson, Jan Lehnardt, and Noah Slater are writing for O&amp;#8217;Reilly. It is still a work in progress, but the &lt;a href='http://books.couchdb.org/relax/' title='CouchDB: The Definitive Guide'&gt;latest draft&lt;/a&gt; is available online.&lt;/p&gt;

&lt;p&gt;For API reference my source is the &lt;a href='http://wiki.apache.org/couchdb/' title='CouchDB Wiki'&gt;CouchDB Wiki&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Finally, as the CouchDB developers will tell you, the most up-to-date reference for the latest CouchDB features is the included test suite. This is a set of tests written in JavaScript that you can run from CouchDB&amp;#8217;s web interface to verify that your build of the latest SVN checkout is working correctly. These tests are run externally and access the database server via its HTTP API; so you don&amp;#8217;t have to know any nitty gritty Erlang stuff to understand what the tests are doing. When any changes to the API are introduced this test suite is updated accordingly.&lt;/p&gt;</content>
 </entry>
 
 
 
 <entry>
   <title>How to install Haskell "Batteries Included" Platform on Ubuntu Jaunty</title>
   <link href="http://sitr.us/2009/07/02/how-to-install-haskell-platform-on-ubuntu-jaunty.html" />
   <updated>2009-07-02T00:00:00-07:00</updated>
   <id>http://sitr.us/2009/07/02/how-to-install-haskell-platform-on-ubuntu-jaunty</id>
   <content type="html">&lt;p&gt;Just for kicks I thought I would take another shot at some Haskell programming. To get all of the common libraries and the automated package installer, cabal, I set up the &lt;a href='http://hackage.haskell.org/platform/'&gt;Haskell Platform&lt;/a&gt;. Here is how I did it.&lt;/p&gt;

&lt;p&gt;Ubuntu Jaunty includes a package for the Haskell compiler, ghc, at version 6.8. The Haskell Platform installer will roll its eyes at you if you try to proceed with this version of ghc. So the first step is to install ghc 6.10.&lt;/p&gt;

&lt;p&gt;Paste these lines into &lt;code&gt;/etc/apt/sources.list.d/haskell.list&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;deb http://ppa.launchpad.net/someone561/ppa/ubuntu jaunty main
deb-src http://ppa.launchpad.net/someone561/ppa/ubuntu jaunty main&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To get the key to verify packages from that PPA, run this optional command:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys E51D9310&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then update your package list and install Haskell:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo apt-get update
sudo apt-get install ghc6 ghc6-prof ghc6-doc haddock&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The Haskell Platform website does not list a package for Ubuntu yet. So &lt;a href='http://hackage.haskell.org/platform/'&gt;download the source installer&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Before you run the installer you will want to install the necessary build dependencies:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo apt-get install libglut-dev happy alex libedit-dev zlib1g-dev&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Please leave a comment if you discover that I have left out any dependencies.&lt;/p&gt;

&lt;p&gt;To perform the final installation step you will also need to have checkinstall installed:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo apt-get install checkinstall&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Unpack the source installer wherever you like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;tar -xzf haskell-platform-2009.2.0.1.tar.gz&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Finally &lt;code&gt;cd&lt;/code&gt; into the installer directory and run the generic installation procedure:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;./configure
make
sudo checkinstall -y&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will build and install a deb package called &lt;code&gt;haskell-platform&lt;/code&gt;. If you ever want to remove Haskell Platform just uninstall that package.&lt;/p&gt;

&lt;p&gt;If all of the above worked, you should be good to go. You compile Haskell code with &lt;code&gt;ghc&lt;/code&gt;. You can run an interactive read-eval-print-loop with &lt;code&gt;ghci&lt;/code&gt;. And you can install Haskell libraries with &lt;code&gt;cabal&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Updated 2009-07-23&lt;/em&gt;: Added zlib1g-dev to list of build dependencies. Thanks Jack Siler and Fernand.&lt;br /&gt;&lt;em&gt;Updated 2009-08-01&lt;/em&gt;: Added step for installing checkinstall. Thanks Paulo.&lt;/p&gt;</content>
 </entry>
 
 
 
 <entry>
   <title>Database Queries the CouchDB Way</title>
   <link href="http://sitr.us/2009/06/30/database-queries-the-couchdb-way.html" />
   <updated>2009-06-30T00:00:00-07:00</updated>
   <id>http://sitr.us/2009/06/30/database-queries-the-couchdb-way</id>
   <content type="html">&lt;p&gt;&lt;a href='http://couchdb.apache.org/'&gt;CouchDB&lt;/a&gt; is a document-oriented database. It has no rows or tables. Instead CouchDB is a collection of JSON documents. It uses a map-reduce pattern to index data. Queries in CouchDB pull data from what are essentially stored procedures called views. A view is made up of a map function and optionally a reduce function. Ninety percent of the time all you need is the map function, so I will focus on map-only views here.&lt;/p&gt;

&lt;p&gt;A map function is a JavaScript function that takes a single document as an argument and emits any number of key/value pairs. Both the key and the value can be any JSON value you choose. The map function is run on every document in the database individually and the emitted key/value pairs are used to construct an index of your data.&lt;/p&gt;

&lt;h2 id='a_simple_example'&gt;A Simple Example&lt;/h2&gt;

&lt;p&gt;Imagine you have a database with user records and you want a view of those records using the last name of each user as keys.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;doc&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;doc&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;last_name&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='nx'&gt;emit&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;doc&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;last_name&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;doc&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
    &lt;span class='p'&gt;}&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The above map function will produce and index something like the one below. Because &lt;code&gt;doc&lt;/code&gt; is used as a value for each entry the entire content of each JSON document will be accessible as the indexed values.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;span class='p'&gt;[&lt;/span&gt;
  &lt;span class='p'&gt;...&lt;/span&gt;
  &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='nx'&gt;key&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Clarke&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;value&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='nx'&gt;last_name&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Clarke&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;...&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt; &lt;span class='p'&gt;},&lt;/span&gt;
  &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='nx'&gt;key&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Kelly&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;  &lt;span class='nx'&gt;value&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='nx'&gt;last_name&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Kelly&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;  &lt;span class='p'&gt;...&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt; &lt;span class='p'&gt;},&lt;/span&gt;
  &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='nx'&gt;key&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Smith&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;  &lt;span class='nx'&gt;value&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='nx'&gt;last_name&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Smith&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;  &lt;span class='p'&gt;...&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt; &lt;span class='p'&gt;},&lt;/span&gt;
  &lt;span class='p'&gt;...&lt;/span&gt;
&lt;span class='p'&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Notice that the map function checks each document for a &lt;code&gt;last_name&lt;/code&gt; attribute before emitting a key/value pair. There may be documents in the database that are not user records. By performing that check the view excludes any non-user-record documents from the resulting index.&lt;/p&gt;

&lt;p&gt;If you include the &lt;a href='http://github.com/halorgium/couchdb/blob/2c5f780d8284be5e2cb39f7f61acc5ef8d6fb50d/share/www/script/couch.js'&gt;couch.js&lt;/a&gt; library in a web page you can create client-side queries to pull data from CouchDB over HTTP. The function below will fetch all of the user records from your database by returning the &lt;code&gt;value&lt;/code&gt; of each key/value pair emitted by the view above.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;span class='kd'&gt;function&lt;/span&gt; &lt;span class='nx'&gt;users&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;db&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;db&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;view&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;users/last_names&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;&lt;span class='nx'&gt;rows&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;map&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;dot&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;value&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;));&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;

&lt;span class='c1'&gt;// Run the query and output data to the console.&lt;/span&gt;
&lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;db&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='nx'&gt;CouchDB&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;database-with-users&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
&lt;span class='nx'&gt;console&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;log&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;users&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;db&lt;/span&gt;&lt;span class='p'&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Map functions operate on one document at a time and cannot access data from other documents. The advantage of this is that the functions can process data in any order and can run on any piece of a data set independent of the rest of the set. CouchDB builds static indexes from the output of view map functions so that queries against those views will run quickly. When any documents change CouchDB can incrementally rebuild the indexes for just those documents without having to rebuild entire indexes from scratch.&lt;/p&gt;

&lt;p&gt;The CouchDB design gets you great performance on large data sets. But it means that you cannot pass dynamic parameters to your map function when you run a query. You cannot ask for it to emit only user records with a given last name unless you want to maintain a special view for that particular last name. In most cases it is not practical to build separate views for every query that you might want to run someday. So what you can do is to run a query against the general purpose view above and request only key/value pairs that match a particular key.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;span class='kd'&gt;function&lt;/span&gt; &lt;span class='nx'&gt;find_users_by_last_name&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;db&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;last_name&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;matches&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
    &lt;span class='nx'&gt;matches&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;db&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;view&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;users/last_names&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='nx'&gt;key&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='nx'&gt;last_name&lt;/span&gt; &lt;span class='p'&gt;});&lt;/span&gt;
    &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;matches&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;rows&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;map&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;dot&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;value&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;));&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This client code creates a query that requests data from the &lt;code&gt;last_names&lt;/code&gt; view with a &lt;code&gt;key&lt;/code&gt; parameter. CouchDB will only send back key/value pairs with keys that match the &lt;code&gt;key&lt;/code&gt; parameter. In this case the query will return all user records with last names matching the &lt;code&gt;last_name&lt;/code&gt; argument.&lt;/p&gt;

&lt;p&gt;In a more advanced case you may want to take the first few letters of a last name and look up user records that match.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;span class='kd'&gt;function&lt;/span&gt; &lt;span class='nx'&gt;find_users_whose_last_names_start_with&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;db&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;query&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;matches&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
    &lt;span class='nx'&gt;matches&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;db&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;view&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;users/last_names&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
                      &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='nx'&gt;startkey&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='nx'&gt;query&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
                        &lt;span class='nx'&gt;endkey&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt;   &lt;span class='nx'&gt;query&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;\u9999&amp;quot;&lt;/span&gt; &lt;span class='p'&gt;});&lt;/span&gt;
    &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;matches&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;rows&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;map&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;dot&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;value&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;));&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Data returned by a query is always sorted by key. In the case where the keys are strings the sorting will be lexicographic. The &lt;code&gt;startkey&lt;/code&gt; and &lt;code&gt;endkey&lt;/code&gt; parameters restrict the results of the query to key/value pairs that fall in the given range according to CouchDB&amp;#8217;s sort order.&lt;/p&gt;

&lt;p&gt;When the above function is given the query string &amp;#8220;Ha&amp;#8221;, it will fetch documents with keys sorted after &amp;#8220;Ha&amp;#8221; lexicographically, e.g. &amp;#8220;Hallett&amp;#8221;, &amp;#8220;Hathaway&amp;#8221;, and &amp;#8220;Hazzold&amp;#8221;. The &lt;code&gt;endkey&lt;/code&gt; is created by appending &amp;#8220;\u9999&amp;#8221; to the &lt;code&gt;startkey&lt;/code&gt;. &amp;#8220;\u9999&amp;#8221; is a unicode character that comes after most other characters in lexicographic order and that is unlikely to appear in a data set. Effectively the string &amp;#8220;Ha\u9999&amp;#8221; sorts after every other string that begins with &amp;#8220;Ha&amp;#8221;, but before any string that starts with &amp;#8220;Hb&amp;#8221;.&lt;/p&gt;

&lt;p&gt;Note that CouchDB uses the &lt;a href='http://www.unicode.org/unicode/reports/tr10/'&gt;Unicode Collation Algorithm&lt;/a&gt; to sort strings. Sorting comes out differently than you may be used to if your are accustomed to the ASCII way. UCA collation is intended to mimic the order of strings you would see in a dictionary. For example, two strings that differ only in case will appear together in sorted order. The lower-case string will appear immediately before the upper-case string. So if you force your &lt;code&gt;startkey&lt;/code&gt; to lower-case and your &lt;code&gt;endkey&lt;/code&gt; to upper-case you will get case-insensitive matches. See the &lt;a href='http://wiki.apache.org/couchdb/View_collation'&gt;CouchDB wiki&lt;/a&gt; for more details.&lt;/p&gt;

&lt;h2 id='search_by_keyword'&gt;Search by Keyword&lt;/h2&gt;

&lt;p&gt;Indexing text content can be a hard problem because you need a large index if you want to query data by arbitrary keywords or substrings. Fortunately CouchDB excels at managing large indexes.&lt;/p&gt;

&lt;p&gt;Here is a map function that creates an index of all the words that appear in the text field of every document in a database.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;doc&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;tokens&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
    &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;doc&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;text&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='nx'&gt;tokens&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;doc&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;text&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;split&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='sr'&gt;/[^A-Z0-9\-_]+/i&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt;&lt;span class='nx'&gt;uniq&lt;/span&gt;&lt;span class='p'&gt;();&lt;/span&gt;
        &lt;span class='nx'&gt;tokens&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;map&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;token&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
            &lt;span class='nx'&gt;emit&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;token&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;doc&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
        &lt;span class='p'&gt;});&lt;/span&gt;
    &lt;span class='p'&gt;}&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The code splits text on word boundaries stripping out non-alphanumeric characters. It runs the resulting list of tokens through a unique filter so that only one index key is produced for each word in the text of a single document.&lt;/p&gt;

&lt;p&gt;This is an example of a view that emits more than one key/value pair for each document. The values in each pair are the same for the same document. But a different key is recorded for each word in the document&amp;#8217;s text attribute. The index that would be created by this view for a document with the text &amp;#8220;Live long and prosper&amp;#8221; is below.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;span class='p'&gt;[&lt;/span&gt;
  &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='nx'&gt;key&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;and&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;     &lt;span class='nx'&gt;value&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='nx'&gt;text&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Live long and prosper.&amp;quot;&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt; &lt;span class='p'&gt;},&lt;/span&gt;
  &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='nx'&gt;key&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Live&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;    &lt;span class='nx'&gt;value&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='nx'&gt;text&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Live long and prosper.&amp;quot;&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt; &lt;span class='p'&gt;},&lt;/span&gt;
  &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='nx'&gt;key&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;long&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;    &lt;span class='nx'&gt;value&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='nx'&gt;text&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Live long and prosper.&amp;quot;&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt; &lt;span class='p'&gt;},&lt;/span&gt;
  &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='nx'&gt;key&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;prosper&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;value&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='nx'&gt;text&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Live long and prosper.&amp;quot;&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt;
&lt;span class='p'&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To look up documents that contain a given keyword you just need to create a query with that keyword as the &lt;code&gt;key&lt;/code&gt; parameter. But what if you want to look for documents that contain a list of keywords? You could create index keys for every combination of words in each document. But that index would grow exponentially and might get to be unreasonably large. A better way might be to pick one keyword to perform your query and then to use client code to select the documents that match all of the keywords out of the results returned by CouchDB.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;span class='kd'&gt;function&lt;/span&gt; &lt;span class='nx'&gt;find_documents_by_keywords&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;db&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;keywords&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;possible_matches&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;

    &lt;span class='c1'&gt;// Query documents that include the first keyword.&lt;/span&gt;
    &lt;span class='nx'&gt;possible_matches&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;db&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;view&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;documents/keywords&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; 
                               &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='nx'&gt;key&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='nx'&gt;keywords&lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; &lt;span class='p'&gt;});&lt;/span&gt;

    &lt;span class='c1'&gt;// Pull the value attribute out of each returned key/value&lt;/span&gt;
    &lt;span class='c1'&gt;// pair.&lt;/span&gt;
    &lt;span class='nx'&gt;possible_matches&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;possible_matches&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;rows&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;map&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;dot&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;value&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;));&lt;/span&gt;

    &lt;span class='c1'&gt;// Pick out the documents that include all of the given&lt;/span&gt;
    &lt;span class='c1'&gt;// keywords.&lt;/span&gt;
    &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;possible_matches&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;select&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;m&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;keywords&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;reduce&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kc'&gt;true&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;match&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;keyword&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
            &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;m&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;text&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;match&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;keyword&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class='nx'&gt;match&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
        &lt;span class='p'&gt;});&lt;/span&gt;
    &lt;span class='p'&gt;});&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When you want more dynamic data processing than you can get with pure-CouchDB views, some client-side processing can make up the difference nicely. From a perspective of deploying applications leveraging your users&amp;#8217; CPU cycles for data processing can really help getting your application to scale.&lt;/p&gt;

&lt;p&gt;There is another approach to full text search documented &lt;a href='http://wiki.apache.org/couchdb/Full_text_index_with_view'&gt;on the CouchDB wiki&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id='search_by_substring'&gt;Search by Substring&lt;/h2&gt;

&lt;p&gt;Maybe keyword search isn&amp;#8217;t good enough. Maybe you need to be able to search for occurrences of any substring in a data set.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;doc&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;i&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
    &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;doc&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;text&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='k'&gt;for&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;i&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt; &lt;span class='nx'&gt;i&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='nx'&gt;doc&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;text&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;length&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt; &lt;span class='nx'&gt;i&lt;/span&gt; &lt;span class='o'&gt;+=&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
            &lt;span class='nx'&gt;emit&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;doc&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;text&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;slice&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;i&lt;/span&gt;&lt;span class='p'&gt;),&lt;/span&gt; &lt;span class='nx'&gt;doc&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
        &lt;span class='p'&gt;}&lt;/span&gt;
    &lt;span class='p'&gt;}&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;For each document, this map function emits a key/value pair for every possible substring that runs to the end of the document&amp;#8217;s text. The idea is that the beginning of any substring in the data set can be lined up with the beginning of one of these keys. Here is an example of the index created for a document with the text &amp;#8220;Hello, world!&amp;#8221;:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;span class='p'&gt;[&lt;/span&gt;
  &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='nx'&gt;key&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot; world!&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;       &lt;span class='nx'&gt;value&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='nx'&gt;text&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Hello, world!&amp;quot;&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt; &lt;span class='p'&gt;},&lt;/span&gt;
  &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='nx'&gt;key&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;, world!&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;      &lt;span class='nx'&gt;value&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='nx'&gt;text&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Hello, world!&amp;quot;&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt; &lt;span class='p'&gt;},&lt;/span&gt;
  &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='nx'&gt;key&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;!&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;             &lt;span class='nx'&gt;value&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='nx'&gt;text&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Hello, world!&amp;quot;&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt; &lt;span class='p'&gt;},&lt;/span&gt;
  &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='nx'&gt;key&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;d!&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;            &lt;span class='nx'&gt;value&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='nx'&gt;text&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Hello, world!&amp;quot;&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt; &lt;span class='p'&gt;},&lt;/span&gt;
  &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='nx'&gt;key&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;ello, world!&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;  &lt;span class='nx'&gt;value&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='nx'&gt;text&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Hello, world!&amp;quot;&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt; &lt;span class='p'&gt;},&lt;/span&gt;
  &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='nx'&gt;key&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Hello, world!&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;value&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='nx'&gt;text&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Hello, world!&amp;quot;&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt; &lt;span class='p'&gt;},&lt;/span&gt;
  &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='nx'&gt;key&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;ld!&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;           &lt;span class='nx'&gt;value&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='nx'&gt;text&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Hello, world!&amp;quot;&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt; &lt;span class='p'&gt;},&lt;/span&gt;
  &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='nx'&gt;key&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;llo, world!&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;   &lt;span class='nx'&gt;value&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='nx'&gt;text&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Hello, world!&amp;quot;&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt; &lt;span class='p'&gt;},&lt;/span&gt;
  &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='nx'&gt;key&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;lo, world!&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;    &lt;span class='nx'&gt;value&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='nx'&gt;text&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Hello, world!&amp;quot;&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt; &lt;span class='p'&gt;},&lt;/span&gt;
  &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='nx'&gt;key&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;o, world!&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;     &lt;span class='nx'&gt;value&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='nx'&gt;text&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Hello, world!&amp;quot;&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt; &lt;span class='p'&gt;},&lt;/span&gt;
  &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='nx'&gt;key&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;orld!&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;         &lt;span class='nx'&gt;value&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='nx'&gt;text&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Hello, world!&amp;quot;&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt; &lt;span class='p'&gt;},&lt;/span&gt;
  &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='nx'&gt;key&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;rld!&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;          &lt;span class='nx'&gt;value&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='nx'&gt;text&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Hello, world!&amp;quot;&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt; &lt;span class='p'&gt;},&lt;/span&gt;
  &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='nx'&gt;key&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;world!&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;        &lt;span class='nx'&gt;value&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='nx'&gt;text&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Hello, world!&amp;quot;&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt;
&lt;span class='p'&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The substring that you want to search for can begin at any character within some document&amp;#8217;s text. It may or may not run until the end of that document&amp;#8217;s text field. We have an index with the beginning characters for every possible substring. So we can create a query that asks for a key range that encompasses both the given substring and a substring that runs all the way to the end of the document text.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;span class='kd'&gt;function&lt;/span&gt; &lt;span class='nx'&gt;find_all_by_substring&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;db&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;str&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;db&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;view&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;documents/substrings&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
                   &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='nx'&gt;startkey&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='nx'&gt;str&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
                     &lt;span class='nx'&gt;endkey&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='nx'&gt;str&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;\u9999&amp;quot;&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt;
                  &lt;span class='p'&gt;).&lt;/span&gt;&lt;span class='nx'&gt;rows&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;map&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;dot&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;value&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;));&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;CouchDB does not just sort data when responding to queries. In its internal representation indexes are always sorted by key. So a query with a key range targets a contiguous block of data from the database. Because of that CouchDB can serve up a key range very efficiently.&lt;/p&gt;

&lt;p&gt;Just as with the keyword search, if you want to search for documents that match a list of substrings then get the matches for one of the substrings from CouchDB and use client code to select results that contain all of the rest of the given substrings.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;span class='kd'&gt;function&lt;/span&gt; &lt;span class='nx'&gt;find_all_by_substrings&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;db&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;strs&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;matches&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
    &lt;span class='nx'&gt;matches&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;db&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;view&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;documents/substrings&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
                      &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='nx'&gt;startkey&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='nx'&gt;strs&lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;],&lt;/span&gt;
                        &lt;span class='nx'&gt;endkey&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='nx'&gt;strs&lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;\u9999&amp;quot;&lt;/span&gt; &lt;span class='p'&gt;});&lt;/span&gt;
    &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;matches&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;rows&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;map&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;dot&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;value&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)).&lt;/span&gt;&lt;span class='nx'&gt;select&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;d&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;strs&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;reduce&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;r&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;s&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
            &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;d&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;text&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;match&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;s&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class='nx'&gt;r&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
        &lt;span class='p'&gt;});&lt;/span&gt;
    &lt;span class='p'&gt;});&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If the text of your documents tends to be very long you can avoid a lot of really long keys by limiting the lengths of substring keys in your view. In that case make sure to truncate the key parameters in your queries so that they are not longer than the index keys.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Updated 2009-07-05&lt;/em&gt;: Updated examples to demonstrate that CouchDB stores indexes sorted by key. Thanks to J. Chris Anderson for pointing that out.&lt;br /&gt;&lt;em&gt;Updated 2009-08-06&lt;/em&gt;: Added link to full text search implementation on CouchDB wiki.&lt;br /&gt;&lt;em&gt;Updated 2009-08-09&lt;/em&gt;: Fixed a typo.&lt;/p&gt;

&lt;h2 id='appendix_helper_function_definitions'&gt;Appendix: Helper Function Definitions&lt;/h2&gt;

&lt;p&gt;Some of the functions that I used in the examples above are not built into JavaScript or &lt;a href='http://github.com/halorgium/couchdb/blob/2c5f780d8284be5e2cb39f7f61acc5ef8d6fb50d/share/www/script/couch.js'&gt;couch.js&lt;/a&gt;. Here are definitions of those functions for reference.&lt;/p&gt;

&lt;p&gt;Given an attribute name, &lt;code&gt;dot&lt;/code&gt; returns a function that when given an object returns the value of the specified attribute. This function is used in examples above to get the &lt;code&gt;value&lt;/code&gt; attributes of rows fetched by CouchDB queries.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;span class='kd'&gt;function&lt;/span&gt; &lt;span class='nx'&gt;dot&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;attr&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;obj&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;obj&lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nx'&gt;attr&lt;/span&gt;&lt;span class='p'&gt;];&lt;/span&gt;
    &lt;span class='p'&gt;}&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href='http://en.wikipedia.org/wiki/Map_%28higher-order_function%29'&gt;&lt;code&gt;map&lt;/code&gt;&lt;/a&gt; is an Array method that given a function that takes a single argument returns a new array formed by applying the given function to every element of the original array in turn.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;span class='nb'&gt;Array&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;prototype&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;map&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;func&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;i&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;r&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='p'&gt;[],&lt;/span&gt;
    &lt;span class='k'&gt;for&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;i&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt; &lt;span class='nx'&gt;i&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;length&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt; &lt;span class='nx'&gt;i&lt;/span&gt; &lt;span class='o'&gt;+=&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='nx'&gt;r&lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nx'&gt;i&lt;/span&gt;&lt;span class='p'&gt;]&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;func&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nx'&gt;i&lt;/span&gt;&lt;span class='p'&gt;]);&lt;/span&gt;
    &lt;span class='p'&gt;}&lt;/span&gt;
    &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;r&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
&lt;span class='p'&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href='http://en.wikipedia.org/wiki/Reduce_%28higher-order_function%29'&gt;&lt;code&gt;reduce&lt;/code&gt;&lt;/a&gt; is an Array method that given an initial value and a function that takes two arguments returns a single value produced by applying the given function to every element of the array in turn with the value from the previous function invocation and returning the last result.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;span class='nb'&gt;Array&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;prototype&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;reduce&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;val&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;func&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='kd'&gt;var&lt;/span&gt; &lt;span class='nx'&gt;i&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
    &lt;span class='k'&gt;for&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;i&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt; &lt;span class='nx'&gt;i&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;length&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt; &lt;span class='nx'&gt;i&lt;/span&gt; &lt;span class='o'&gt;+=&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='nx'&gt;val&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nx'&gt;func&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;val&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nx'&gt;i&lt;/span&gt;&lt;span class='p'&gt;]);&lt;/span&gt;
    &lt;span class='p'&gt;}&lt;/span&gt;
    &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;val&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;select&lt;/code&gt; is an Array method that given a test function returns a new array made up of only elements in the original array that pass the test.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;span class='nb'&gt;Array&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;prototype&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;select&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;test&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;reduce&lt;/span&gt;&lt;span class='p'&gt;([],&lt;/span&gt; &lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;r&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;e&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;test&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;e&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
            &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;r&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;concat&lt;/span&gt;&lt;span class='p'&gt;([&lt;/span&gt;&lt;span class='nx'&gt;e&lt;/span&gt;&lt;span class='p'&gt;]);&lt;/span&gt;
        &lt;span class='p'&gt;}&lt;/span&gt; &lt;span class='k'&gt;else&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
            &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;r&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
        &lt;span class='p'&gt;}&lt;/span&gt;
    &lt;span class='p'&gt;});&lt;/span&gt;
&lt;span class='p'&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;uniq&lt;/code&gt; is an Array method that returns a new array with any duplicate values from the original array removed.&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;span class='nb'&gt;Array&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;prototype&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;uniq&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;reduce&lt;/span&gt;&lt;span class='p'&gt;([],&lt;/span&gt; &lt;span class='kd'&gt;function&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;list&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nx'&gt;e&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
        &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;list&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;indexOf&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nx'&gt;e&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
            &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;list&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nx'&gt;concat&lt;/span&gt;&lt;span class='p'&gt;([&lt;/span&gt;&lt;span class='nx'&gt;e&lt;/span&gt;&lt;span class='p'&gt;]);&lt;/span&gt;
        &lt;span class='p'&gt;}&lt;/span&gt; &lt;span class='k'&gt;else&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
            &lt;span class='k'&gt;return&lt;/span&gt; &lt;span class='nx'&gt;list&lt;/span&gt;&lt;span class='p'&gt;;&lt;/span&gt;
        &lt;span class='p'&gt;}&lt;/span&gt;
    &lt;span class='p'&gt;});&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content>
 </entry>
 
 
 
 <entry>
   <title>How to use RSpec to describe a Sinatra application</title>
   <link href="http://sitr.us/2008/07/29/how-to-use-rspec-to-describe-a-sinatra-application.html" />
   <updated>2008-07-29T00:00:00-07:00</updated>
   <id>http://sitr.us/2008/07/29/how-to-use-rspec-to-describe-a-sinatra-application</id>
   <content type="html">&lt;p&gt;This information was written a long time ago and has become pretty outdated.&lt;/p&gt;

&lt;p&gt;&lt;a href='http://sinatrarb.com/'&gt;Sinatra&lt;/a&gt; is a fun little web application microframework. Recently I started working on an application using Sinatra - and since I am working on good programming habits, before I dove into any coding I sat down to work out how to write specs for a Sinatra application.&lt;/p&gt;

&lt;p&gt;Sinatra comes bundled with support for &lt;a href='http://chneukirchen.org/repos/testspec/README'&gt;test/spec&lt;/a&gt;: a spec framework that builds on top of Rail&amp;#8217;s own Test::Unit to provide support for writing specs. Which is a really neat idea. But I have been using &lt;a href='http://rspec.info/'&gt;RSpec&lt;/a&gt; for my other work, and I wanted to continue doing so.&lt;/p&gt;

&lt;p&gt;It turns out that RSpec takes a little bit of manual work to get going with Sinatra. I read a &lt;a href='http://www.gittr.com/index.php/archive/sinatra-rspec-integration-without-a-patch-with-examples/'&gt;helpful article on gittr.com&lt;/a&gt; that pointed me in the right direction. The article advised me to add these lines to my spec files:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='nb'&gt;require&lt;/span&gt; &lt;span class='no'&gt;File&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;expand_path&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='no'&gt;File&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;dirname&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='bp'&gt;__FILE__&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;/your_application&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='nb'&gt;require&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;spec&amp;#39;&lt;/span&gt;
&lt;span class='nb'&gt;require&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;spec/interop/test&amp;#39;&lt;/span&gt;
&lt;span class='nb'&gt;require&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;sinatra/test/unit&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The first line loads your application; the second line loads RSpec; the third loads an RSpec-Test::Unit compatibility layer; and the fourth loads Sinatra&amp;#8217;s test helpers, which are written for Test::Unit.&lt;/p&gt;

&lt;p&gt;Contrary to Sinatra&amp;#8217;s instructions for writing tests, you want to avoid loading &amp;#8216;sinatra/test/spec&amp;#8217;, which defines Sinatra&amp;#8217;s helper methods for test/spec, because that would load test/spec itself which conflicts with RSpec.&lt;/p&gt;

&lt;p&gt;Those instructions mostly worked. I could write and run specs. But I had trouble with matchers. For example, this example:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='n'&gt;it&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;should not have a cookie&amp;quot;&lt;/span&gt;
  &lt;span class='n'&gt;instance&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;cookie&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;should&lt;/span&gt; &lt;span class='n'&gt;be_nil&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Would give an error message like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;undefined method `be_nil&amp;#39; for nil:NilClass&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Which I&amp;#8217;m sure you can imagine is pretty annoying.&lt;/p&gt;

&lt;p&gt;It was easy enough to identify &amp;#8216;sinatra/test/unit&amp;#8217; as the root of the problem. When I removed that line RSpec&amp;#8217;s matchers worked fine; but then I didn&amp;#8217;t get Sinatra&amp;#8217;s test helpers, which make spec-writing much easier. So that wasn&amp;#8217;t a great solution either.&lt;/p&gt;

&lt;p&gt;Examining Sinatra&amp;#8217;s code, I found that all &amp;#8216;sinatra/test/unit&amp;#8217; does is to load &amp;#8216;sinatra/test/methods&amp;#8217; - the actual helper methods - and mixes them into Test::Unit::TestCase. So I bypassed &amp;#8216;sinatra/test/unit&amp;#8217; by copying and adapting some code from it to make the top of my spec file look like this:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='nb'&gt;require&lt;/span&gt; &lt;span class='no'&gt;File&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;expand_path&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='no'&gt;File&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;dirname&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='bp'&gt;__FILE__&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;/your_application&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='nb'&gt;require&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;spec&amp;#39;&lt;/span&gt;
&lt;span class='nb'&gt;require&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;spec/interop/test&amp;#39;&lt;/span&gt;
&lt;span class='nb'&gt;require&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;sinatra/test/methods&amp;#39;&lt;/span&gt;

&lt;span class='kp'&gt;include&lt;/span&gt; &lt;span class='ss'&gt;Sinatra&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='ss'&gt;:Test&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Methods&lt;/span&gt;

&lt;span class='ss'&gt;Sinatra&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='ss'&gt;:Application&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;default_options&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;merge!&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;
  &lt;span class='ss'&gt;:env&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='ss'&gt;:test&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
  &lt;span class='ss'&gt;:run&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='kp'&gt;false&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
  &lt;span class='ss'&gt;:raise_errors&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='kp'&gt;true&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt;
  &lt;span class='ss'&gt;:logging&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='kp'&gt;false&lt;/span&gt;
&lt;span class='p'&gt;)&lt;/span&gt;

&lt;span class='no'&gt;Sinatra&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;application&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;options&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='kp'&gt;nil&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Since that is a fair amount of setup, I moved all of it into a separate file called spec_helper.rb, which I loaded into my actual spec files. Because I am weird enough to write a Sinatra application that is split into multiple files and multiple spec files.&lt;/p&gt;

&lt;p&gt;Anyway, now my specs run just as they should, with Sinatra&amp;#8217;s helpers and everything:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='n'&gt;it&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;should deliver a cookie&amp;quot;&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt;
  &lt;span class='n'&gt;get_it&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;/cookie&amp;#39;&lt;/span&gt;
  &lt;span class='vi'&gt;@response&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;should&lt;/span&gt; &lt;span class='n'&gt;be_ok&lt;/span&gt;
  &lt;span class='vi'&gt;@response&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;headers&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;Content-Type&amp;#39;&lt;/span&gt;&lt;span class='o'&gt;].&lt;/span&gt;&lt;span class='n'&gt;should&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;application/x-baked-goods&amp;#39;&lt;/span&gt;
  &lt;span class='vi'&gt;@response&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;body&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;should_not&lt;/span&gt; &lt;span class='n'&gt;be_empty&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The next challenge was to write specs for Sinatra helpers. Although Sinatra actions and helpers generally appear in the outermost namespace, the DSL methods that define them actually bind the helpers to Sinatra::EventContext. You can&amp;#8217;t invoke helper methods directly from an example context; you have to create an instance of Sinatra::EventContext and send the method call to that - much the same way Rails instantiates a subclass of ActionController::Base to handle a controller action. Here is the code you will want in your example groups:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='n'&gt;before&lt;/span&gt; &lt;span class='ss'&gt;:all&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt;
  &lt;span class='n'&gt;request&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;mock&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;request&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='n'&gt;response&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;mock&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;response&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:body&lt;/span&gt;&lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='kp'&gt;nil&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='n'&gt;route_params&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;mock&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;route_params&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='vi'&gt;@event_context&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='ss'&gt;Sinatra&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt;&lt;span class='ss'&gt;:EventContext&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;request&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;response&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;route_params&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A &lt;code&gt;body=&lt;/code&gt; method has to be defined on the response mock to prevent an error. But it doesn&amp;#8217;t have to actually do anything. With that setup code in place, you can do this:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='n'&gt;it&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;should use a helper to make cookies&amp;quot;&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt;
  &lt;span class='vi'&gt;@event_context&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;bake_a_cookie&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;should&lt;/span&gt; &lt;span class='n'&gt;be_an_instance_of&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='no'&gt;Cookie&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and write something like this in your application:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='n'&gt;helper&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt;
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;bake_a_cookie&lt;/span&gt;
    &lt;span class='no'&gt;Cookie&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='ss'&gt;:kind&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='ss'&gt;:chocolate_chip&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And now you have a reasonably complete speccing setup. There are still a couple of issues though. For one thing, the spec helpers are missing a much needed &lt;code&gt;assigns[]&lt;/code&gt; method. As it stands there is no good way to pry apart the behavior of an action if there is no convenient method call to stub. You can only define the parameters that are passed to it, and read response. On the upside, this does help to enforce good behavior-driven development.&lt;/p&gt;

&lt;p&gt;The other issue is more of an annoyance than a serious problem. It seems that somewhere in all of this there are one or two &lt;code&gt;method_missing&lt;/code&gt; definitions that bounce calls back and forth. If call a method that is not defined, you generally won&amp;#8217;t get an &amp;#8220;undefined method&amp;#8221; error, you will get a &amp;#8220;stack level too deep&amp;#8221; error instead. This is particularly unhelpful because it does not tell you what class received the undefined method, or which method is undefined. So a little extra manual stack tracing is required when this happens.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Update&lt;/em&gt; 10/11/08: The Sinatra application that led to this article is now open source and is available at &lt;a href='http://github.com/hallettj/restful_captcha'&gt;http://github.com/hallettj/restful_captcha&lt;/a&gt;. If you want to see the RSpec techniques that I used in context, check out the code there.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Updated 2009-08-09&lt;/em&gt;: This article is pretty outdated. Added a note to that effect.&lt;/p&gt;</content>
 </entry>
 
 
 
 <entry>
   <title>International Phonetic Alphabet</title>
   <link href="http://sitr.us/2007/10/02/international-phonetic-alphabet.html" />
   <updated>2007-10-02T00:00:00-07:00</updated>
   <id>http://sitr.us/2007/10/02/international-phonetic-alphabet</id>
   <content type="html">&lt;p&gt;In &lt;a href='http://sitr.us/ling/2007/09/24/anatomy-of-a-syllable/'&gt;last week&amp;#8217;s post&lt;/a&gt; I provided phonetic transcriptions of some example words using the International Phonetic Alphabet, or IPA for short. I thought it would be helpful to follow that up with some information about what the IPA is, and how to read it. And as a bonus, after learning about IPA transcription you will be able to better read pronunciation guides on Wikipedia.&lt;/p&gt;

&lt;p&gt;You have probably seen many phonetic transcriptions before - especially as pronunciation guides in dictionaries. In dictionaries it is common to see a transcription convention that uses English spelling conventions to represent sounds. For example, the word &amp;#8220;elucidate&amp;#8221; might be transcribed as (ee-LOO-suh-date). That system is handy because it is immediately familiar to anyone who has experience reading stuff in English. But it has drawbacks too. There are a few main problems that are especially important for linguists; there are lots of linguists all over the world who are used to languages with entirely different spelling conventions. For example, the sound in English that is represented as &amp;#8220;y&amp;#8221; - the consonant, not the vowel - is written in Icelandic as &amp;#8220;j&amp;#8221;. There are also a lot of languages with sounds that just don&amp;#8217;t exist in English. Linguists need to be able to transcribe those sounds; but since they don&amp;#8217;t exist in English there is no spelling convention to represent them. In fact there is no one language with enough spelling conventions to represent every sound in every language in the world. And finally, English spelling is ambiguous, as is the spelling of almost any language. That is already demonstrated by the need to add a note to distinguish &amp;#8220;y&amp;#8221; the consonant from &amp;#8220;y&amp;#8221; the vowel or any of the other vowel sounds represented by &amp;#8220;y&amp;#8221;.&lt;/p&gt;

&lt;p&gt;To solve all these problems, a group of linguistics developed the International Phonetic Alphabet in the late nineteenth century. The first standardized version was created in 1888. But it has been revised somewhat since then. The purpose of IPA is to provide a standard set of symbols that are used to represent sounds so that the same symbols always represent the sounds, even to people from different language backgrounds. Using the IPA it is theoretically possible to represent every sound in every language in the world. Though occasionally a new language is discovered with a new sound that we didn&amp;#8217;t know anything about before, which has to be quickly added to the IPA.&lt;/p&gt;

&lt;p&gt;IPA was originally developed by French and British linguists, so it uses characters derived from the Latin alphabet and symbols are matched to sounds in a ways that are generally familiar to Europeans. But even in the Western world people have different ideas about how to spell things, so the IPA adopts some different phonetic conventions from different languages. For example, I mentioned earlier that the sound represented by &amp;#8220;y&amp;#8221; in English is spelled &amp;#8220;j&amp;#8221; in, among others languages, Icelandic; and in fact the symbol for that sound in IPA is [j]. Here is &lt;a href='http://www.linguiste.org/phonetics/ipa/chart/'&gt;the complete IPA chart in its most recent revision&lt;/a&gt;. And by the way: in IPA, the word &amp;#8220;elucidate&amp;#8221; is transcribed [i&amp;#8217;lu.sə.deɪt].&lt;/p&gt;

&lt;p&gt;The sound an IPA symbol represents is described by the &lt;em&gt;place of articulation&lt;/em&gt; of the sound, an the &lt;em&gt;manner of articulation&lt;/em&gt;. When you voice a consonant you, you press your tongue against the roof of your mouth, or in some cases you press your lips together or put the tip of your tongue between your teeth. The exact spot on where you press your tongue is the place of articulation. For example, when you say [t] you press the tip of your tongue against a spot towards the front of your mouth called the alveolar ridge; whereas when you say [k] you press the back of your tongue against your soft palate, which linguists call the velum. [t] and [k] have the same manner of articulation - they are both plosives, which means that they are articulated by completely stopping air from flowing out of the mouth for a moment. But they have different places of articulation. Early on in a linguist&amp;#8217;s career he learns all about the structures of the mouth, throat, and nose to learn how each can be used to produce various sounds. I will explain some of the details in future articles; in the meantime it would probably be easiest to look up IPA symbols using &lt;a href='http://en.wikipedia.org/wiki/IPA_Chart_for_English'&gt;this IPA chart on Wikipedia&lt;/a&gt;, which is specially designed for English speakers and provides example words to illustrate each sound.&lt;/p&gt;

&lt;p&gt;Wikipedia provides the transcription for the English &amp;#8220;r&amp;#8221; as [ɹ]. This is the most technically correct transcription, since in IPA [r] represents a rolled &amp;#8220;r&amp;#8221;, which is heard in Spanish. In linguistics speak, [r] is a trill and [ɹ] is a liquid. However, English doesn&amp;#8217;t have a trill, so people transcribing English often use [r] instead of [ɹ] because the former is more familiar - and easier to type. It is considered acceptable to make substitutions like that in cases where readers are unlikely to be confused by the switch. So when I transcribe an English word using [r] instead of [ɹ] I&amp;#8217;m not actually trying to make you practice pronouncing trills.&lt;/p&gt;

&lt;p&gt;As an aside, the rolled &amp;#8220;r&amp;#8221; in French is not the same sound as the rolled &amp;#8220;r&amp;#8221; in Spanish. The French &amp;#8220;r&amp;#8221; is transcribed [ʀ]. Both sounds are trills, so they share the same manner of articulation; but they have different places of articulation. [ɹ] is alveolar, meaning that to pronounce it the tip of the tongue is positioned on the alveolar ridge, in the same spot it is placed when pronouncing [t]. The sound is produced by vibrating the tongue against the roof of the mouth, which is what makes it a trill. To pronounce [ʀ], the back of the tongue is placed against the uvula and vibrates against that.&lt;/p&gt;

&lt;p&gt;To make the alphabet more flexible, IPA employs a number of diacritics. Diacritics are small marks placed above or below a character. In IPA they are used to describe characteristics of a sound that differ slightly from the sound usually represented by a bare character. Last week I talked about consonants that are used as syllable nuclei, which are called syllabic consonants. Syllabicity is considered a phonological feature, so it is indicated with a diacritic. For example, the syllabic version of [n] is [n̩].&lt;/p&gt;

&lt;p&gt;Another example of a diacritic is ʰ, which is used to indicate aspiration. Did you know that the letter &amp;#8220;p&amp;#8221; in English is used to represent two different sounds? The &amp;#8220;p&amp;#8221; sounds in &amp;#8220;pull&amp;#8221; and &amp;#8220;stop&amp;#8221; are slightly different. You can tell if you put your hand in front of your mouth, less than an inch away, and say each word. You will feel a puff of air on your hand when you say the &amp;#8220;p&amp;#8221; in &amp;#8220;pull&amp;#8221;; there is a puff when you say &amp;#8220;stop&amp;#8221; too, but it is not nearly as strong. A sound that makes that strong puff of air is said to be &lt;em&gt;aspirated&lt;/em&gt;, and is marked with a diacritic that looks like a superscripted &amp;#8220;h&amp;#8221;. So the IPA representation for an aspirated &amp;#8220;p&amp;#8221; is /pʰ/ and an unaspirated &amp;#8220;p&amp;#8221; is simply /p/.&lt;/p&gt;

&lt;p&gt;Even though they are technically different sounds, English speakers treat /p/ and /pʰ/ as being the same. So they are written with the same letter. And in IPA they are usually both transcribed as [p] for simplicity. But on occasion it is important to have the ability to distinguish the two. The difference between sounds that are exactly the same and sounds that are treated as the same by language speakers is a very important consideration in linguistics - and it has to do with the sudden switch from square brackets to slashes surrounding the transcriptions above. I will talk about that in a future article too.&lt;/p&gt;</content>
 </entry>
 
 
 
 <entry>
   <title>Anatomy of a Syllable</title>
   <link href="http://sitr.us/2007/09/24/anatomy-of-a-syllable.html" />
   <updated>2007-09-24T00:00:00-07:00</updated>
   <id>http://sitr.us/2007/09/24/anatomy-of-a-syllable</id>
   <content type="html">&lt;p&gt;The syllable is a constant feature in every spoken language in the world. Each language has its own rules about what kinds of syllables are allowed, and what kinds aren&amp;#8217;t - but the general structure is the same everywhere.&lt;/p&gt;

&lt;p&gt;A syllable has as many as three parts: &lt;em&gt;onset&lt;/em&gt;, &lt;em&gt;nucleus&lt;/em&gt;, and &lt;em&gt;coda&lt;/em&gt;. The onset and the coda are consonants, or consonant clusters, that appear at the beginning and the end of the syllable respectively. The nucleus forms the the core of the syllable; it is most often a vowel, or a combination of vowels - but there are many exceptions to that. If you examine enough languages you can find almost every kind phone used as a syllable nucleus. In the word &amp;#8220;far&amp;#8221;, [f] is the syllable onset, [a] is the nucleus, and [r] the coda. If a coda is present in a syllable, the nucleus and the coda form a single unit called a &lt;em&gt;rhyme&lt;/em&gt;; otherwise the nucleus makes up the rhyme by itself. Looking at &amp;#8220;far&amp;#8221; again, [ar] forms the rhyme. A syllable does not necessarily have to have an onset or a coda - depending on the language - but a nucleus is always present.&lt;/p&gt;

&lt;p&gt;Even in English, syllable nuclei are not restricted to vowels. For example, in the monosyllabic word, &amp;#8220;hmm&amp;#8221;, the syllable nucleus is [ṃ], which is a consonant but is more specifically a &lt;em&gt;nasal&lt;/em&gt;. Another nasal, [n], can be seen as a syllable nucleus in the word &amp;#8220;isn&amp;#8217;t&amp;#8221;, which is transcribed into the &lt;a href='http://en.wikipedia.org/wiki/International_Phonetic_Alphabet'&gt;International Phonetic Alphabet (IPA)&lt;/a&gt; as [ɪzzṇt]. In this case there are two syllables, and [ṇ] forms the nucleus of the second syllable.&lt;/p&gt;

&lt;p&gt;The small dot underneath the characters ṇ and ṃ indicates that the sound represented is a &lt;em&gt;syllabic consonant&lt;/em&gt;, which is any consonant that forms a syllable nucleus. Vowels are not marked with the same diacritic because they are always considered to be syllabic. Usually syllabicity is marked in IPA with a vertical stroke under the character instead of a dot; but in this case a dot was as close as I could get.&lt;/p&gt;

&lt;p&gt;Anyone following closely may notice that it is difficult to decide exactly how to divide &amp;#8220;isn&amp;#8217;t&amp;#8221; into syllables. It seems like it should be either [&amp;#8216;ɪz.ṇt], or [&amp;#8216;ɪ.zṇt], where the dot (.) represents a syllable boundary and the apostrophe (&amp;#8216;) represents the beginning of a stressed syllable; but it is tricky to figure out whether the [z] is the coda of the first syllable or the onset of the second syllable. That is because in the [z] in &amp;#8220;isn&amp;#8217;t&amp;#8221; demonstrates &lt;em&gt;ambisyllabicity&lt;/em&gt;, a common feature in English that I will write about in a future article. The short explanation is that [z] is both an onset and a coda, which is why I transcribed the word with two [z]&amp;#8217;s. Anyway, in both analyses [ṇ] forms the nucleus of the second syllable, so we don&amp;#8217;t need to worry about the placement of [z] for now.&lt;/p&gt;

&lt;p&gt;There are also arguably cases where a &lt;em&gt;liquid&lt;/em&gt; forms the nucleus of a syllable in English. The liquids in English are [l] and [r]. Consider the word &amp;#8220;sir&amp;#8221; and the second syllable of &amp;#8220;apple&amp;#8221;. If it is the case that the liquids in these syllables are the nuclei, then the words would be transcribed as [sṛ] and [æppḷ] respectively. However, not everybody agrees with that interpretation, and so these words are often analyzed as [sər] and [æppəl]. That would make the syllable nuclei [ə], which is a vowel. And by the way, the [p] in &amp;#8220;apple&amp;#8221; is also ambisyllabic.&lt;/p&gt;

&lt;p&gt;The reason vowels are so likely to form syllable nuclei is that they are the most &lt;em&gt;sonorous&lt;/em&gt; sounds available in spoken language. It is a general rule that syllable nuclei are formed by sonorous phones. Liquids and nasals are right behind vowels in that they are more sonorous than any other type of consonant. But it is possible to find syllable nuclei in other languages that are considerably less sonorant than any of the above. For example, there is at least one &lt;a href='http://en.wikipedia.org/wiki/Berber_languages'&gt;Berber language&lt;/a&gt; that contains syllables like [tḳt], where the nucleus of the syllable is [ḳ].&lt;/p&gt;

&lt;p&gt;The onset and coda are always made up of consonants. Many languages have strict rules about how many consonants can appear, and what sort of order they appear in. English is relatively lax in this respect, so we can see syllables with several consonants clustered together in both positions. For example, &amp;#8220;scrumptious&amp;#8221;, transcribed as [&amp;#8216;skrʌmp.ʃəs], has three distinct consonant phones in the onset and two in the coda of the first syllable. But notice that you would never see a word in English like [&amp;#8216;rksʌpm.ʃəs], which would probably be spelled &amp;#8220;rksupmtious&amp;#8221;. Try pronouncing that and see what happens - and remember that it&amp;#8217;s cheating to make the [r] or the [m] into separate syllables!&lt;/p&gt;

&lt;p&gt;Consonants in syllable onsets and codas are also governed by sonority. There is a rule, called the &lt;em&gt;sonority sequencing generalization&lt;/em&gt;, that says that the sonority of a syllable peaks at the nucleus and decreases toward either boundary. So the sonority of consonants in the onset is supposed to increase going forward, and the sonority in the coda is supposed to fall of. This is a generalization, so there are exceptions - but if you deviate too much from the rule the result becomes difficult to pronounce. In the made-up word above I reversed the order of the consonants in the onset and coda of the first syllable, thus making the sonority sequence &amp;#8220;wrong&amp;#8221;.&lt;/p&gt;

&lt;p&gt;Every sound in a language has a place somewhere in the sonority hierarchy. And every language has its own sonority hierarchy ordering. So for example [star] is easy for English speakers to pronounce, but you don&amp;#8217;t see a word like [tsar]: [t] is more sonorous than [s] in English. But in Russian it is not uncommon to see a word like [tsar].&lt;/p&gt;

&lt;p&gt;Restrictions on what is allowed in a syllable vary from language to language. Not all languages allow as many consonants to be clustered in a syllable onset as English does, while some allow more. Some languages require every syllable to have an onset, while others allow naked nuclei. Syllable codas are especially restricted. For example, in Mandarin Chinese the only syllable codas that are allowed are nasals. There are no languages that forbid onsets, but many languages don&amp;#8217;t allow syllable codas to appear at all.&lt;/p&gt;

&lt;p&gt;For more information, and some neat diagrams, visit &lt;a href='http://www.sil.org/LINGUISTICS/GlossaryOfLinguisticTerms/WhatIsASyllable.htm'&gt;What is a syllable?&lt;/a&gt; and &lt;a href='http://en.wikipedia.org/wiki/Syllable'&gt;the Wikipedia entry for &amp;#8220;Syllable&amp;#8221;&lt;/a&gt;.&lt;/p&gt;</content>
 </entry>
 
 
 
 <entry>
   <title>Deixis</title>
   <link href="http://sitr.us/2007/09/17/deixis.html" />
   <updated>2007-09-17T00:00:00-07:00</updated>
   <id>http://sitr.us/2007/09/17/deixis</id>
   <content type="html">&lt;p&gt;When someone says to you, &amp;#8220;here&amp;#8221; or &amp;#8220;now&amp;#8221;, you probably know what he means. &amp;#8220;Here&amp;#8221; might the room that you are both sitting in. &amp;#8220;Now&amp;#8221; would be the span of time you spent sitting together. But if either word were uttered under different circumstances, it could mean something very different. For example, if I called you from the Andes and I used the word, &amp;#8220;here&amp;#8221;, it would mean a mountainside somewhere - possibly thousands of miles away from the aforementioned room. The same word can mean both the room and the mountainside because of &lt;a href='http://en.wikipedia.org/wiki/Deixis'&gt;deixis&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Deixis is a form of &lt;a href='http://en.wikipedia.org/wiki/Exophora'&gt;exophora&lt;/a&gt;, which is an utterance that is given meaning by the context it is uttered in. Specifically, deixis represents the speech event itself: deictic expressions reference the speaker, the speaker&amp;#8217;s utterances, the speaker&amp;#8217;s location, and the time at which the speech event occurs. There are different types of deictic expressions that refer to each particular aspect.&lt;/p&gt;

&lt;p&gt;&lt;a href='http://en.wikipedia.org/wiki/Personal_pronoun'&gt;Personal pronouns&lt;/a&gt;, such as &amp;#8220;I&amp;#8221;, &amp;#8220;you&amp;#8221;, &amp;#8220;he&amp;#8221;, and &amp;#8220;she&amp;#8221;, are deictic expressions. &amp;#8220;I&amp;#8221; refers simply to the speaker. The other pronouns are defined by the relation the referenced person has to the speaker in the discourse. As the role of speaker switches from person to person, the context represented by deixis in understood by participants of the discourse to change too.&lt;/p&gt;

&lt;p&gt;Location and time are a little more complicated. Whenever someone speaks - or writes, or is quoted, etc. - there is an implicit deictic center that is formed in the minds of the speaker and any listeners. A deictic center is the point in space and time that spatial and temporal deictic expressions refer to. &amp;#8220;Here&amp;#8221; and &amp;#8220;now&amp;#8221; are the simplest examples. The verbs &amp;#8220;to come&amp;#8221; and to &amp;#8220;to go&amp;#8221; are also spatial deictic expressions: &amp;#8220;to come&amp;#8221; means motion towards the deictic center, and &amp;#8220;to go&amp;#8221; means motion away.&lt;/p&gt;

&lt;p&gt;Based on this analysis, the phrase &amp;#8220;come here&amp;#8221; seems redundant at first. But actually the addition of &amp;#8220;here&amp;#8221; can be important, due to a phenomenon called &lt;em&gt;sympathetic deixis&lt;/em&gt;. It is not uncommon, especially in phone conversations, to hear an utterance like, &amp;#8220;I will come by later&amp;#8221;. For the speaker to move toward the deictic center is almost nonsensical when the speaker is the deictic center. But in this case sympathetic deixis causes the deictic center to shift from the speaker&amp;#8217;s location to the listener&amp;#8217;s location. So motion towards the deictic center actually translates to motion toward the listener.&lt;/p&gt;

&lt;p&gt;Note that the shift caused by sympathetic deixis does not necessarily affect all the aspects of deixis. In the example above the meanings of personal pronouns do not change after the deictic center has shifted; in a similar sentence, &amp;#8220;I will come to see you&amp;#8221;, &amp;#8220;I&amp;#8221; refers to the speaker, and &amp;#8220;you&amp;#8221; refers to the listener - as would be expected with or without a shifted deictic center.&lt;/p&gt;

&lt;p&gt;An especially fun deictic puzzle is often heard in answering machine messages like, &amp;#8221;I&amp;#8217;m not here right now&amp;#8221;. It isn&amp;#8217;t possible that the deictic center is fixed upon the speaker during this message, because it is not possible for the speaker to not occupy his own location. So there must be sympathetic deixis in effect to shift the deictic center either spatially or temporally. As someone who has been on the receiving end of this message, I expect &amp;#8220;here&amp;#8221; to mean the location where the message was recorded, and &amp;#8220;now&amp;#8221; to be the time when I am calling. By that analysis the spatial location of the deictic center remains fixed on the location of the speech event, while the temporal aspect shifts to the listening event via sympathetic deixis. There is another possible analysis where both spatial and temporal sympathetic deictic shifts occur. In that case the spatial shift does not move the location of the deictic center to the listener, but instead moves it to the place where the listener expects it to be: in this case wherever the speaker&amp;#8217;s phone is. Under either analysis, the answering machine example demonstrates that deictic shifts can be temporal as well as spatial.&lt;/p&gt;

&lt;p&gt;There are other forms of deictic expressions. There is a more complete list in &lt;a href='http://en.wikipedia.org/wiki/Deixis'&gt;the Wikipedia article on deixis&lt;/a&gt;.&lt;/p&gt;</content>
 </entry>
 
 
 
</feed>
