<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="https://www.w3.org/2005/Atom" xmlns:sy="https://purl.org/rss/1.0/modules/syndication/" xmlns:dc="https://purl.org/dc/elements/1.1/" xmlns:content="https://purl.org/rss/1.0/modules/content/" xmlns:wfw="https://wellformedweb.org/CommentAPI/" xmlns:slash="https://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>inventive title</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/rbuckton/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/rbuckton/feed.xml</link>
    <description>News, samples, tips and tricks for Windows Mobile, SharePoint, ASP.NET and the Ajax Control Toolkit</description>
    <lastBuildDate>Tue, 16 Apr 2019 05:26:40 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Promise.js 2.0 – Promise Framework for JavaScript</title>
      <link>https://docs.microsoft.com/archive/blogs/rbuckton/promise-js-2-0-promise-framework-for-javascript</link>
      <pubDate>Mon, 15 Aug 2011 13:10:00 GMT</pubDate>
      <dc:creator><![CDATA[Ron Buckton]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/rbuckton/2011/08/15/promise-js-2-0-promise-framework-for-javascript/</guid>
      <description><![CDATA[Well over a year ago I posted an article describing how to employ an asynchrony concept known as a...]]></description>
      <content:encoded><![CDATA[<p>Well over a year ago <a href="https://blogs.msdn.com/b/rbuckton/archive/2010/01/29/promises-and-futures-in-javascript.aspx" target="_blank">I posted</a> an article describing how to employ an asynchrony concept known as a <a href="https://en.wikipedia.org/wiki/Promise_(programming)" target="_blank">Promise</a>.&nbsp; Since then a number of implementations of Promises have shown up in libraries such as <a href="https://jquery.org" target="_blank">jQuery</a> <a href="https://api.jquery.com/category/deferred-object/" target="_blank">Deferred</a> and <a href="https://commonjs.org" target="_blank">CommonJS</a>.&nbsp; I&rsquo;ve updated the sources and removed the dependency on ASP.NET Ajax, however the current version depends on features of ECMAScript 5, which is supported in IE 9, Chrome, and Firefox.&nbsp; If you need support for Safari, Opera, or IE 8 and under you need to use an <a href="https://www.bing.com/search?q=es5+polyfill&amp;go=&amp;qs=n&amp;sk=&amp;form=QBLH" target="_blank">ES5 Polyfill</a>.&nbsp; In addition the license has been changed from MSR-LA (Non-Commercial) to MS-PL which allows commercial use.</p>
<h1>Introduction</h1>
<p><a href="https://en.wikipedia.org/wiki/Promise_(programming)" target="_blank">Promise</a> is a programming model that deals with deferred results in concurrent programming. The basic idea around promises are that rather than issuing a blocking call for a resource (IO, Network, etc.) you can immediately return a promise for a future value that will eventually be fulfilled. This allows you to write non-blocking logic that executes asynchronously without having to write a lot of synchronization and plumbing code.</p>
<h1>License</h1>
<p>Promise.js is licensed under the Microsoft Public License (MS-PL).</p>
<h1>Source</h1>
<p><a href="https://aka.ms/promisejs">promise.zip</a></p>
<h1>Description</h1>
<p>Promises are especially useful in JavaScript due to the fact that most of the JavaScript runtimes do not provide a means to block execution to wait on a result from a possibly long-running operation.&nbsp; To facilitate rich interactive experiences in the browser, asynchrony is imperative.&nbsp; All of the current generation (and many earlier generation) browsers support XMLHttpRequest as a means to asynchronously fetch content from the server on demand. Without a Promise model, fetching html from the server might use code like the following:</p>
<div class="csharpcode">
<pre><span class="lnum"> 1: </span><span class="kwrd">function</span> fetchSync(url) {</pre>
<pre><span class="lnum"> 2: </span>  <span class="kwrd">var</span> xhr = <span class="kwrd">new</span> XMLHttpRequest();</pre>
<pre><span class="lnum"> 3: </span>  xhr.open(url, <span class="str">"GET"</span>, <span class="kwrd">false</span>, <span class="kwrd">null</span>, <span class="kwrd">null</span>);</pre>
<pre><span class="lnum"> 4: </span>  xhr.send(<span class="kwrd">null</span>);</pre>
<pre><span class="lnum"> 5: </span>  <span class="kwrd">if</span> (xhr.status == 200) {</pre>
<pre><span class="lnum"> 6: </span>    <span class="kwrd">return</span> xhr;</pre>
<pre><span class="lnum"> 7: </span>  }</pre>
<pre><span class="lnum"> 8: </span>  <span class="kwrd">throw</span> <span class="kwrd">new</span> Error(xhr.statusText);</pre>
<pre><span class="lnum"> 9: </span>}</pre>
<pre><span class="lnum"> 10: </span> </pre>
<pre><span class="lnum"> 11: </span><span class="kwrd">function</span> fetchAsync(url, callback, errorCallback) { </pre>
<pre><span class="lnum"> 12: </span>  <span class="kwrd">var</span> xhr = <span class="kwrd">new</span> XMLHttpRequest();</pre>
<pre><span class="lnum"> 13: </span>  xhr.onreadystatechange = <span class="kwrd">function</span>() {</pre>
<pre><span class="lnum"> 14: </span>    <span class="kwrd">if</span> (xhr.readyState == 4) {</pre>
<pre><span class="lnum"> 15: </span>      <span class="kwrd">if</span> (xhr.status == 200) {</pre>
<pre><span class="lnum"> 16: </span>        callback(xhr);</pre>
<pre><span class="lnum"> 17: </span>      } </pre>
<pre><span class="lnum"> 18: </span>      <span class="kwrd">else</span> {</pre>
<pre><span class="lnum"> 19: </span>        errorCallback(<span class="kwrd">new</span> Error(xhr.statusText));</pre>
<pre><span class="lnum"> 20: </span>      }</pre>
<pre><span class="lnum"> 21: </span>    }</pre>
<pre><span class="lnum"> 22: </span>  }</pre>
<pre><span class="lnum"> 23: </span>  xhr.open(url, <span class="str">"GET"</span>, <span class="kwrd">true</span>, <span class="kwrd">null</span>, <span class="kwrd">null</span>);</pre>
<pre><span class="lnum"> 24: </span>  xhr.send(<span class="kwrd">null</span>);</pre>
<pre><span class="lnum"> 25: </span>}</pre>
</div>
<p>In the first example, the RSS feed is fetched synchronously (see line 3). In this case the code is straightforward but the request is blocking, which means script execution is suspended until the request is completed or fails. This is not optimal in an AJAX application as it can impact the interactivity of the page.</p>
<p>The second example attempts to alleviate the blocking call by introducing a callback that will be executed when the request completes. This is advantageous as it is non-blocking, however the programming model can become inconsistent if you are working with different asynchronous data sources including loading local resources, performing computationally intensive tasks (such as xml transforms or other data transformation), etc.</p>
<p>To actually use the resulting feed you might have to do some additional work:</p>
<div class="csharpcode">
<pre><span class="lnum"> 1: </span>fetchAsync(</pre>
<pre><span class="lnum"> 2: </span>  <span class="str">"/feeds/changes.rss"</span>,</pre>
<pre><span class="lnum"> 3: </span>  <span class="kwrd">function</span> (rssXhr) {</pre>
<pre><span class="lnum"> 4: </span>    fetchAsync(</pre>
<pre><span class="lnum"> 5: </span>      <span class="str">"/resources/rss.xsl"</span>,</pre>
<pre><span class="lnum"> 6: </span>      <span class="kwrd">function</span> (xslXhr) {</pre>
<pre><span class="lnum"> 7: </span>        document.getElementById(<span class="str">"host"</span>).innerHTML =</pre>
<pre><span class="lnum"> 8: </span>          rssXhr.responseXML.transformNode(xslXhr.responseXML);</pre>
<pre><span class="lnum"> 9: </span>      },</pre>
<pre><span class="lnum"> 10: </span>      <span class="kwrd">function</span> (e) {</pre>
<pre><span class="lnum"> 11: </span>        document.getElementById(<span class="str">"host"</span>).innerHTML = </pre>
<pre><span class="lnum"> 12: </span>          <span class="str">"Error: "</span> + e.message;</pre>
<pre><span class="lnum"> 13: </span>      });</pre>
<pre><span class="lnum"> 14: </span>  }, <span class="kwrd">function</span> (e) {</pre>
<pre><span class="lnum"> 15: </span>    document.getElementById(<span class="str">"host"</span>).innerHTML = </pre>
<pre><span class="lnum"> 16: </span>      <span class="str">"Error: "</span> + e.message;</pre>
<pre><span class="lnum"> 17: </span>  });</pre>
</div>
<p>In this example we now have two asynchronous calls for content, however one depends on the other and as a result we can&rsquo;t take advantage of concurrent requests to speed up the process.</p>
<p>Using promises we could instead do the following:</p>
<div class="csharpcode">
<pre><span class="lnum"> 1: </span><span class="kwrd">var</span> changes = Promise.get(<span class="str">"/feeds/changes.rss"</span>);</pre>
<pre><span class="lnum"> 2: </span><span class="kwrd">var</span> xsl = Promise.get(<span class="str">"/resources/rss.xsl"</span>);</pre>
<pre><span class="lnum"> 3: </span>Promise</pre>
<pre><span class="lnum"> 4: </span>  .all(changes, xsl)</pre>
<pre><span class="lnum"> 5: </span>  .then(<span class="kwrd">function</span>(ar) {</pre>
<pre><span class="lnum"> 6: </span>    document.getElementById(<span class="str">"host"</span>).innerHTML = </pre>
<pre><span class="lnum"> 7: </span>      ar[0].responseXML.transformNode(ar[1].responseXML);</pre>
<pre><span class="lnum"> 8: </span>  }, <span class="kwrd">function</span>(e) {</pre>
<pre><span class="lnum"> 9: </span>     document.getElementById(<span class="str">"host"</span>).innerText = e.message;</pre>
<pre><span class="lnum"> 10: </span>  })</pre>
</div>
<p>Another feature of Promises is&nbsp; pipelining, the ability to create a series of operations based on the result of a promise.&nbsp; Then <strong>then()</strong> function is used to pipeline a promise, creating a new Promise based on the eventual output of the source. For example:</p>
<div class="csharpcode">
<pre><span class="lnum"> 1: </span>Promise</pre>
<pre><span class="lnum"> 2: </span>  .get(<span class="str">"somefeed.xml"</span>)</pre>
<pre><span class="lnum"> 3: </span>  .then({ </pre>
<pre><span class="lnum"> 4: </span>    resolve: <span class="kwrd">function</span>(xhr) { <span class="kwrd">return</span> xhr.responseXML }),</pre>
<pre><span class="lnum"> 5: </span>    progress: <span class="kwrd">function</span>(xhr) { console.log(<span class="str">"Loading..."</span>) }</pre>
<pre><span class="lnum"> 6: </span>  })</pre>
<pre><span class="lnum"> 7: </span>  .then({</pre>
<pre><span class="lnum"> 8: </span>    resolve: <span class="kwrd">function</span>(xdoc) { console.log(xdoc.xml) },</pre>
<pre><span class="lnum"> 9: </span>    reject: <span class="kwrd">function</span>(e) { console.error(e.message) )</pre>
<pre><span class="lnum"> 10: </span>  })</pre>
</div>
<p>On line 2 we fetch an xml document from the server. On line 4 we create a pipeline that will eventually convert the response into an XML document.&nbsp; On line 8 when the document is finally available we can handle the results.</p>
<p>Here's an example using piplined promises and JSONP to get the public timeline from Twitter:</p>
<div class="csharpcode">
<pre><span class="lnum"> 1: </span>Promise</pre>
<pre><span class="lnum"> 2: </span>  .jsonp(<span class="str">"https://api.twitter.com/1/statuses/public_timeline.json"</span>)</pre>
<pre><span class="lnum"> 3: </span>  .then(<span class="kwrd">function</span> (data) {</pre>
<pre><span class="lnum"> 4: </span>    data.forEach(<span class="kwrd">function</span> (tweet) {</pre>
<pre><span class="lnum"> 5: </span>      <span class="kwrd">var</span> newTweet = createTweet(tweet);</pre>
<pre><span class="lnum"> 6: </span>      document.getElementById(<span class="str">"tweets"</span>).appendChild(newTweet);</pre>
<pre><span class="lnum"> 7: </span>    });</pre>
<pre><span class="lnum"> 8: </span>  })</pre>
<pre><span class="lnum"> 9: </span>  .then({ reject: <span class="kwrd">function</span> (e) { alert(e) } });</pre>
</div>
<p>Here's an example of computing a future factorial using Web Workers (supported in Safari, Chrome, Firefox, Opera and IE 10 (as of Platform Preview 2):</p>
<div class="csharpcode">
<pre><span class="lnum"> 1: </span><span class="rem">// factorial.js</span></pre>
<pre><span class="lnum"> 2: </span>onmessage = <span class="kwrd">function</span>(e) {</pre>
<pre><span class="lnum"> 3: </span>  <span class="kwrd">var</span> value = e.data;</pre>
<pre><span class="lnum"> 4: </span>  <span class="kwrd">var</span> result = 0;</pre>
<pre><span class="lnum"> 5: </span>  <span class="kwrd">do</span> {</pre>
<pre><span class="lnum"> 6: </span>    result += value;</pre>
<pre><span class="lnum"> 7: </span>  }</pre>
<pre><span class="lnum"> 8: </span>  <span class="kwrd">while</span> (--value &gt; 0);</pre>
<pre><span class="lnum"> 9: </span>  postMessage(result);</pre>
<pre><span class="lnum"> 10: </span>}</pre>
</div>
<div class="csharpcode">
<pre><span class="lnum"></span></pre>
<pre><span class="lnum"> 1: </span><span class="rem">// client.js</span></pre>
<pre><span class="lnum"> 2: </span>Promise</pre>
<pre><span class="lnum"> 3: </span>  .work(<span class="str">"factorial.js"</span>, 10)</pre>
<pre><span class="lnum"> 4: </span>  .then(<span class="kwrd">function</span>(result) { console.log(result) })</pre>
</div>
<h1>Documentation</h1>
<pre class="csharpcode"><span class="rem">// PromiseSource</span>
<span class="kwrd">var</span> source = <span class="kwrd">new</span> PromiseSource()
<span class="rem">/// &lt;summary&gt;Creates a new PromiseSource&lt;/summary&gt;</span>

source.isCanceled
<span class="rem">/// &lt;value type="Boolean"&gt;Gets a value indicating whether the Promise was </span>
<span class="rem">/// canceled&lt;/value&gt;</span>

source.promise
<span class="rem">/// &lt;value type="Promise"&gt;</span>
<span class="rem">/// Gets the Promise for the current PromiseSource</span>
<span class="rem">/// &lt;/value&gt;</span>

source.resolve(value)
<span class="rem">/// &lt;summary&gt;Resolve the promise using the provided value&lt;/summary&gt;</span>
<span class="rem">/// &lt;param name="value" type="Object" optional="true" mayBeNull="true"&gt;</span>
<span class="rem">/// The value for the promise</span>
<span class="rem">/// &lt;/param&gt;</span>

source.reject(error)
<span class="rem">/// &lt;summary&gt;Reject the promise using the provided error&lt;/summary&gt;</span>
<span class="rem">/// &lt;param name="error" type="Error"&gt;The error for the promise&lt;/param&gt;</span>

source.progress(value)
<span class="rem">/// &lt;summary&gt;Send a progress notification using the provided value&lt;/summary&gt;</span>
<span class="rem">/// &lt;param name="value" type="Object" optional="true" mayBeNull="true" /&gt;</span>

<span class="kwrd">var</span> registration = source.cleanup(cleanupCallback)
<span class="rem">/// &lt;summary&gt;</span>
<span class="rem">/// Register a callback used to cleanup when the related promise is canceled</span>
<span class="rem">/// &lt;/summary&gt;</span>
<span class="rem">/// &lt;param name="callback" type="Function"&gt;</span>
<span class="rem">/// The callback function to execute</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;returns type="Function"&gt;</span>
<span class="rem">/// A function that can be used to unregister the cleanup callback</span>
<span class="rem">/// &lt;/returns&gt;</span>

source.cancel(dueTime)
<span class="rem">/// &lt;summary&gt;</span>
<span class="rem">/// Cancels the promise and executes cleanup callbacks immediately or </span>
<span class="rem">/// optionally after a period of time</span>
<span class="rem">/// &lt;/summary&gt;</span>
<span class="rem">/// &lt;param name="dueTime" type="Number" integer="true" optional="true"&gt;</span>
<span class="rem">/// Optional. The time in milliseconds to wait before canceling the promise</span>
<span class="rem">/// &lt;/param&gt;</span>


<span class="rem">// Promise</span>
<span class="kwrd">var</span> promise = <span class="kwrd">new</span> Promise(initCallback)
<span class="rem">/// &lt;summary&gt;</span>
<span class="rem">/// Creates a new Promise for the provided completion callback</span>
<span class="rem">/// &lt;/summary&gt;</span>
<span class="rem">/// &lt;param name="init" type="Function"&gt;</span>
<span class="rem">/// A callback used to initialize the promise.</span>
<span class="rem">/// &lt;signature&gt;</span>
<span class="rem">/// &lt;param name="source" type="PromiseSource"&gt;</span>
<span class="rem">/// The object used to resolve the promise</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;/signature&gt;</span>
<span class="rem">/// &lt;/param&gt;</span>

promise.isComplete
<span class="rem">/// &lt;value type="Boolean"&gt;</span>
<span class="rem">/// Gets a value indicating whether the Promise has completed</span>
<span class="rem">/// &lt;/value&gt;</span>

promise.isFaulted
<span class="rem">/// &lt;value type="Boolean"&gt;</span>
<span class="rem">/// Gets a value indicating whether the Promise is faulted</span>
<span class="rem">/// &lt;/value&gt;</span>

promise.isCanceled
<span class="rem">/// &lt;value type="Boolean"&gt;</span>
<span class="rem">/// Gets a value indicating whether the Promise was canceled</span>
<span class="rem">/// &lt;/value&gt;</span>

promise.cancel(dueTime)
<span class="rem">/// &lt;summary&gt;</span>
<span class="rem">/// Cancels the promise and executes cleanup callbacks immediately or </span>
<span class="rem">/// optionally after a period of time</span>
<span class="rem">/// &lt;/summary&gt;</span>
<span class="rem">/// &lt;param name="dueTime" type="Number" integer="true" optional="true"&gt;</span>
<span class="rem">/// Optional. The time in milliseconds to wait before canceling the promise</span>
<span class="rem">/// &lt;/param&gt;</span>

<span class="kwrd">var</span> newPromise = promise.then(resolve, reject, progress)
<span class="kwrd">var</span> newPromise = promise.when(resolve, reject, progress)
<span class="rem">/// &lt;summary&gt;</span>
<span class="rem">/// Creates a new promise that executes an action based on the value of the </span>
<span class="rem">/// antecedent promise.</span>
<span class="rem">/// &lt;/summary&gt;</span>
<span class="rem">/// &lt;param name="resolve" type="Function" optional="true" mayBeNull="true"&gt;</span>
<span class="rem">/// The callback that is executed when the promise resolves successfully.</span>
<span class="rem">/// Its results are fed into a new Promise.</span>
<span class="rem">/// &lt;signature&gt;</span>
<span class="rem">/// &lt;param name="value" type="Object"&gt;</span>
<span class="rem">/// The value from the antecedent promise</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;returns type="Object"&gt;The result for the new promise&lt;/param&gt;</span>
<span class="rem">/// &lt;/signature&gt;</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;param name="reject" type="Function" optional="true" mayBeNull="true"&gt;</span>
<span class="rem">/// The callback that is executed when the promise fails. Its results are </span>
<span class="rem">/// fed into a new Promise.</span>
<span class="rem">/// &lt;signature&gt;</span>
<span class="rem">/// &lt;param name="value" type="Object"&gt;</span>
<span class="rem">/// The error raised from the antecedent promise</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;returns type="Object"&gt;The result for the new promise&lt;/param&gt;</span>
<span class="rem">/// &lt;/signature&gt;</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;param name="progress" type="Function" optional="true" mayBeNull="true"&gt;</span>
<span class="rem">/// The callback that is executed when a promise posts progress.</span>
<span class="rem">/// &lt;signature&gt;</span>
<span class="rem">/// &lt;param name="value" type="Object"&gt;</span>
<span class="rem">/// The progress value from the antecedent promise</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;/signature&gt;</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;returns type="Promise"&gt;</span>
<span class="rem">/// The promise created for the provided callbacks</span>
<span class="rem">/// &lt;/returns&gt;</span>

<span class="kwrd">var</span> newPromise = promise.then(options)
<span class="kwrd">var</span> newPromise = promise.when(options)
<span class="rem">/// &lt;summary&gt;</span>
<span class="rem">/// Creates a new promise that executes an action based on the value of the </span>
<span class="rem">/// antecedent promise. </span>
<span class="rem">/// &lt;/summary&gt;</span>
<span class="rem">/// &lt;param name="options" type="Object"&gt;</span>
<span class="rem">/// An object literal for the arguments "resolve", "reject", and "progress"</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;returns type="Promise"&gt;</span>
<span class="rem">/// The promise created for the provided callbacks</span>
<span class="rem">/// &lt;/returns&gt;</span>

<span class="kwrd">var</span> newPromise = promise.get(name)
<span class="rem">/// &lt;summary&gt;</span>
<span class="rem">/// Creates a promise for the value of the data property with the specified </span>
<span class="rem">/// name from the result of this promise</span>
<span class="rem">/// &lt;/summary&gt;</span>
<span class="rem">/// &lt;param name="name" type="String"&gt;The name of the data property&lt;/param&gt;</span>
<span class="rem">/// &lt;returns type="Promise"&gt;</span>
<span class="rem">/// A new Promise that returns the value of the data property</span>
<span class="rem">/// &lt;/returns&gt;</span>

<span class="kwrd">var</span> newPromise = promise.put(name, value)
<span class="rem">/// &lt;summary&gt;</span>
<span class="rem">/// Creates a promise that completes without a value after setting the value </span>
<span class="rem">/// of the data property with the specified name from the result of this </span>
<span class="rem">/// promise</span>
<span class="rem">/// &lt;/summary&gt;</span>
<span class="rem">/// &lt;param name="name" type="String"&gt;The name of the data property&lt;/param&gt;</span>
<span class="rem">/// &lt;param name="value" type="Object" mayBeNull="true"&gt;</span>
<span class="rem">/// The value for the data property</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;returns type="Promise"&gt;</span>
<span class="rem">/// A new Promise with no value that completes after the value of the data </span>
<span class="rem">/// property is set</span>
<span class="rem">/// &lt;/param&gt;</span>

<span class="kwrd">var</span> newPromise = promise.post(name, args)
<span class="rem">/// &lt;summary&gt;</span>
<span class="rem">/// Creates a Promise that returns the result of calling the named function </span>
<span class="rem">/// with the supplied arguments on the result of this promise. Arguments are </span>
<span class="rem">/// passed in a fashion similar to Function.prototype.apply</span>
<span class="rem">/// &lt;/summary&gt;</span>
<span class="rem">/// &lt;param name="name" type="String"&gt;The name of the function&lt;/param&gt;</span>
<span class="rem">/// &lt;param name="args" type="Array"&gt;</span>
<span class="rem">/// An array of arguments for the function</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;returns type="Promise"&gt;</span>
<span class="rem">/// A new Promise that returns the value of the function call</span>
<span class="rem">/// &lt;/returns&gt;</span>

<span class="kwrd">var</span> newPromise = promise.send(name, ...args)
<span class="rem">/// &lt;summary&gt;</span>
<span class="rem">/// Creates a Promise that returns the result of calling the named function </span>
<span class="rem">/// with the supplied arguments on the result of this promise. Arguments are </span>
<span class="rem">/// passed in a fashion similar to Function.prototype.call</span>
<span class="rem">/// &lt;/summary&gt;</span>
<span class="rem">/// &lt;param name="name" type="String"&gt;The name of the function&lt;/param&gt;</span>
<span class="rem">/// &lt;param name="args" type="Object" paramArray="true"&gt;</span>
<span class="rem">/// A parameter array of arguments for the function</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;returns type="Promise"&gt;</span>
<span class="rem">/// A new Promise that returns the value of the function call</span>
<span class="rem">/// &lt;/returns&gt;</span>

<span class="kwrd">var</span> newPromise = promise.unwrap()
<span class="rem">/// &lt;summary&gt;</span>
<span class="rem">/// Creates a Promise for the underlying value of a Promise who's result is </span>
<span class="rem">/// itself a Promise</span>
<span class="rem">/// &lt;/summary&gt;</span>
<span class="rem">/// &lt;result type="Promise"&gt;</span>
<span class="rem">/// A promise for the underlying value of the Promise</span>
<span class="rem">/// &lt;/result&gt;</span>

<span class="kwrd">var</span> newPromise = promise.end()
<span class="rem">/// &lt;summary&gt;</span>
<span class="rem">/// Creates a Promise that throws any unhandled exception to the host object.</span>
<span class="rem">/// &lt;/summary&gt;</span>
<span class="rem">/// &lt;returns type="Promise" /&gt;</span>

Promise.canUseWorker
<span class="rem">/// &lt;value static="true" type="Boolean"&gt;</span>
<span class="rem">/// Gets a value indicating whether Web Workers are supported</span>
<span class="rem">/// &lt;/value&gt;</span>

Promise.isPromise(value)
<span class="rem">/// &lt;summary&gt;Determines whether the provided value is a Promise&lt;/summary&gt;</span>
<span class="rem">/// &lt;param name="promise" type="Object"&gt;</span>
<span class="rem">/// The object that may be a promise</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;returns type="Boolean"&gt;</span>
<span class="rem">/// True if the value provided is a Promise, otherwise false</span>
<span class="rem">/// &lt;/returns&gt;</span>

<span class="kwrd">var</span> promise = Promise.resolve(value)
<span class="rem">/// &lt;summary&gt;Returns the provided value as a Promise&lt;/summary&gt;</span>
<span class="rem">/// &lt;param name="value" type="Object" mayBeNull="true"&gt;</span>
<span class="rem">/// The value to Promise</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;returns type="Promise"&gt;The Promise for the value&lt;/summary&gt;</span>
<span class="rem">/// &lt;remarks&gt;</span>
<span class="rem">/// If the provided value is already a Promise it is returned. If it is a </span>
<span class="rem">/// PromiseSource its associated Promise is returned. Otherwise, a new </span>
<span class="rem">/// Promise is created and fully resolved with the provided value</span>
<span class="rem">/// &lt;/remarks&gt;</span>

<span class="kwrd">var</span> promise = Promise.reject(error)
<span class="rem">/// &lt;summary&gt;</span>
<span class="rem">/// Creates a Promise that is faulted using the provided Error</span>
<span class="rem">/// &lt;summary&gt;</span>
<span class="rem">/// &lt;param name="error" type="Error" /&gt;</span>
<span class="rem">/// &lt;returns type="Promise"&gt;The faulted Promise&lt;/returns&gt;</span>

<span class="kwrd">var</span> promise = Promise.delay(dueTime, value)
<span class="rem">/// &lt;summary&gt;</span>
<span class="rem">/// Creates a Promise that completes after a period of time using the </span>
<span class="rem">/// optionally provided value</span>
<span class="rem">/// &lt;/summary&gt;</span>
<span class="rem">/// &lt;param name="dueTime" type="Number" integer="true"&gt;</span>
<span class="rem">/// The due time in milliseconds at which the Promise will complete</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;param name="value" type="Object" optional="true" mayBeNull="true"&gt;</span>
<span class="rem">/// An optional value to use as the result of the Promise</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;returns type="Promise" /&gt;</span>

<span class="kwrd">var</span> promise = Promise.start(func, dueTime)
<span class="rem">/// &lt;summary&gt;</span>
<span class="rem">/// Creates and schedules a Promise to execute the provided function at a </span>
<span class="rem">/// later time</span>
<span class="rem">/// &lt;/summary&gt;</span>
<span class="rem">/// &lt;param name="func" type="Function"&gt;</span>
<span class="rem">/// The callback to execute whose return value will be the result of the </span>
<span class="rem">/// Promise.</span>
<span class="rem">/// &lt;signature&gt;</span>
<span class="rem">/// &lt;returns type="Object"&gt;The result for the Promise&lt;/returns&gt;</span>
<span class="rem">/// &lt;/signature&gt;</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;param name="dueTime" type="Number" integer="true" optional="true"&gt;</span>
<span class="rem">/// The due time at which to start the callback. The default is immediately</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;returns type="Promise" /&gt;</span>

<span class="kwrd">var</span> promise = Promise.when(promise, resolve, reject, progress)
<span class="rem">/// &lt;summary&gt;</span>
<span class="rem">/// Creates a new promise that executes an action based on the value of the </span>
<span class="rem">/// antecedent promise.</span>
<span class="rem">/// &lt;/summary&gt;</span>
<span class="rem">/// &lt;param name="promise" type="Object"&gt;</span>
<span class="rem">/// The promise to monitor for a result. If the argument is not a Promise, </span>
<span class="rem">/// one will be created for it</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;param name="resolve" type="Function" optional="true" mayBeNull="true"&gt;</span>
<span class="rem">/// The callback that is executed when the promise resolves successfully. </span>
<span class="rem">/// Its results are fed into a new Promise.</span>
<span class="rem">/// &lt;signature&gt;</span>
<span class="rem">/// &lt;param name="value" type="Object"&gt;</span>
<span class="rem">/// The value from the antecedent promise</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;returns type="Object"&gt;The result for the new promise&lt;/param&gt;</span>
<span class="rem">/// &lt;/signature&gt;</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;param name="reject" type="Function" optional="true" mayBeNull="true"&gt;</span>
<span class="rem">/// The callback that is executed when the promise fails. Its results are </span>
<span class="rem">/// fed into a new Promise.</span>
<span class="rem">/// &lt;signature&gt;</span>
<span class="rem">/// &lt;param name="value" type="Object"&gt;</span>
<span class="rem">/// The error raised from the antecedent promise</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;returns type="Object"&gt;The result for the new promise&lt;/param&gt;</span>
<span class="rem">/// &lt;/signature&gt;</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;param name="progress" type="Function" optional="true" mayBeNull="true"&gt;</span>
<span class="rem">/// The callback that is executed when a promise posts progress.</span>
<span class="rem">/// &lt;signature&gt;</span>
<span class="rem">/// &lt;param name="value" type="Object"&gt;</span>
<span class="rem">/// The progress value from the antecedent promise</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;/signature&gt;</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;returns type="Promise"&gt;</span>
<span class="rem">/// The promise created for the provided callbacks</span>
<span class="rem">/// &lt;/returns&gt;</span>

<span class="kwrd">var</span> promise = Promise.when(options)
<span class="rem">/// &lt;summary&gt;</span>
<span class="rem">/// Creates a new promise that executes an action based on the value of the </span>
<span class="rem">/// antecedent promise.</span>
<span class="rem">/// &lt;/summary&gt;</span>
<span class="rem">/// &lt;param name="options" type="Object"&gt;</span>
<span class="rem">/// An object literal for the arguments "promise", "resolve", "reject", and </span>
<span class="rem">/// "progress"</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;returns type="Promise"&gt;</span>
<span class="rem">/// The promise created for the provided callbacks</span>
<span class="rem">/// &lt;/returns&gt;</span>

<span class="kwrd">var</span> promise = Promise.any(...promises)
<span class="rem">/// &lt;summary&gt;</span>
<span class="rem">/// Creates a promise that resolves when at least one promise provided </span>
<span class="rem">/// resolves. Arguments are passed as a parameter array</span>
<span class="rem">/// &lt;/summary&gt;</span>
<span class="rem">/// &lt;param name="promises" type="Object" paramArray="true"&gt;</span>
<span class="rem">/// A parameter array of objects to wait for</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;returns type="Promise"&gt;</span>
<span class="rem">/// A Promise whose result is the result of the first promise to resolve or </span>
<span class="rem">/// fail.</span>
<span class="rem">/// &lt;/returns&gt;</span>

<span class="kwrd">var</span> promise = Promise.all(...promises)
<span class="rem">/// &lt;summary&gt;</span>
<span class="rem">/// Creates a promise that resolves when all of the provided promises resolve </span>
<span class="rem">/// or fail. Arguments are passed as a parameter array</span>
<span class="rem">/// &lt;/summary&gt;</span>
<span class="rem">/// &lt;param name="promises" type="Object" paramArray="true"&gt;</span>
<span class="rem">/// A parameter array of objects to wait for</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;returns type="Promise"&gt;</span>
<span class="rem">/// A Promise whose result is an in-order array of the results of the </span>
<span class="rem">/// promises provided</span>
<span class="rem">/// &lt;/returns&gt;</span>

<span class="kwrd">var</span> promise = Promise.work(url, message)
<span class="rem">/// &lt;summary&gt;</span>
<span class="rem">/// Creates a Promise for a result posted by a Web Worker thread</span>
<span class="rem">/// &lt;/summary&gt;</span>
<span class="rem">/// &lt;param name="url" type="String"&gt;</span>
<span class="rem">/// The url to the script for the web worker</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;param name="message" type="Object" optional="true" mayBeNull="true"&gt;</span>
<span class="rem">/// An optional message to send to start the worker</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;returns type="Promise"&gt;</span>
<span class="rem">/// A Promise for the first message posted by the Web Worker</span>
<span class="rem">/// &lt;/returns&gt;</span>
<span class="rem">/// &lt;remarks&gt;</span>
<span class="rem">/// This is a simplified approach to Web Worker-based promises. The first </span>
<span class="rem">/// message posted by the worker becomes the result and the worker is then </span>
<span class="rem">/// immediately terminated.</span>
<span class="rem">/// &lt;/remarks&gt;</span>

<span class="kwrd">var</span> promise = Promise.work(options)
<span class="rem">/// &lt;summary&gt;</span>
<span class="rem">/// Creates a Promise for a result posted by a Web Worker thread</span>
<span class="rem">/// &lt;/summary&gt;</span>
<span class="rem">/// &lt;param name="options" type="Object"&gt;</span>
<span class="rem">/// An object literal for the arguments "url" and "message"</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;returns type="Promise"&gt;</span>
<span class="rem">/// A Promise for the first message posted by the Web Worker</span>
<span class="rem">/// &lt;/returns&gt;</span>
<span class="rem">/// &lt;remarks&gt;</span>
<span class="rem">/// This is a simplified approach to Web Worker-based promises. The first </span>
<span class="rem">/// message posted by the worker becomes the result and the worker is then </span>
<span class="rem">/// immediately terminated</span>
<span class="rem">/// &lt;/remarks&gt;</span>

<span class="kwrd">var</span> promise = Promise.get(url, username, password, headers, query)
<span class="rem">/// &lt;summary&gt;</span>
<span class="rem">/// Issues an HTTP GET request for the content at the provided url</span>
<span class="rem">/// &lt;/summary&gt;</span>
<span class="rem">/// &lt;param name="url" type="String"&gt;The url for the content&lt;/param&gt;</span>
<span class="rem">/// &lt;param name="username" type="String" optional="true" mayBeNull="true"&gt;</span>
<span class="rem">/// The username for the request.</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;param name="password" type="String" optional="true" mayBeNull="true"&gt;</span>
<span class="rem">/// The password for the request.</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;param name="headers" type="Object" optional="true" mayBeNull="true"&gt;</span>
<span class="rem">/// A JSON object containing headers for the request.</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;param name="query" type="Object" optional="true" mayBeNull="true"&gt;</span>
<span class="rem">/// A JSON object or String containing the querystring for the </span>
<span class="rem">/// request.</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;returns type="Promise"&gt;</span>
<span class="rem">/// A Promise whose result is an XMLHttpRequest object</span>
<span class="rem">/// &lt;/returns&gt;</span>

<span class="kwrd">var</span> promise = Promise.get(options)
<span class="rem">/// &lt;summary&gt;</span>
<span class="rem">/// Issues an HTTP GET request for the content at the provided url</span>
<span class="rem">/// &lt;/summary&gt;</span>
<span class="rem">/// &lt;param name="options" type="Object"&gt;</span>
<span class="rem">/// An object literal for the arguments "url", "username", "password", </span>
<span class="rem">/// "headers", and "query".</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;returns type="Promise"&gt;</span>
<span class="rem">/// A Promise whose result is an XMLHttpRequest object</span>
<span class="rem">/// &lt;/returns&gt;</span>

<span class="kwrd">var</span> promise = Promise.put(url, username, password, headers, query, body)
<span class="rem">/// &lt;summary&gt;</span>
<span class="rem">/// Issues an HTTP PUT request for the content at the provided url</span>
<span class="rem">/// &lt;/summary&gt;</span>
<span class="rem">/// &lt;param name="url" type="String"&gt;The url for the content&lt;/param&gt;</span>
<span class="rem">/// &lt;param name="username" type="String" optional="true" mayBeNull="true"&gt;</span>
<span class="rem">/// The username for the request.</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;param name="password" type="String" optional="true" mayBeNull="true"&gt;</span>
<span class="rem">/// The password for the request.</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;param name="headers" type="Object" optional="true" mayBeNull="true"&gt;</span>
<span class="rem">/// A JSON object containing headers for the request.</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;param name="query" type="Object" optional="true" mayBeNull="true"&gt;</span>
<span class="rem">/// A JSON object or String containing the querystring for the request.</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;param name="body" type="Object" optional="true" mayBeNull="true"&gt;</span>
<span class="rem">/// A JSON object or String containing the body for the request.</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;returns type="Promise"&gt;</span>
<span class="rem">/// A Promise whose result is an XMLHttpRequest object</span>
<span class="rem">/// &lt;/returns&gt;</span>

<span class="kwrd">var</span> promise = Promise.put(options)
<span class="rem">/// &lt;summary&gt;</span>
<span class="rem">/// Issues an HTTP PUT request for the content at the provided url</span>
<span class="rem">/// &lt;/summary&gt;</span>
<span class="rem">/// &lt;param name="options" type="Object"&gt;</span>
<span class="rem">/// An object literal for the arguments "url", "username", "password", </span>
<span class="rem">/// "headers", "query", and "body"</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;returns type="Promise"&gt;</span>
<span class="rem">/// A Promise whose result is an XMLHttpRequest object</span>
<span class="rem">/// &lt;/returns&gt;</span>

<span class="kwrd">var</span> promise = Promise.post(url, username, password, headers, query, body)
<span class="rem">/// &lt;summary&gt;</span>
<span class="rem">/// Issues an HTTP POST request for the content at the provided url</span>
<span class="rem">/// &lt;/summary&gt;</span>
<span class="rem">/// &lt;param name="url" type="String"&gt;The url for the content&lt;/param&gt;</span>
<span class="rem">/// &lt;param name="username" type="String" optional="true" mayBeNull="true"&gt;</span>
<span class="rem">/// The username for the request.</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;param name="password" type="String" optional="true" mayBeNull="true"&gt;</span>
<span class="rem">/// The password for the request.</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;param name="headers" type="Object" optional="true" mayBeNull="true"&gt;</span>
<span class="rem">/// A JSON object containing headers for the request.</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;param name="query" type="Object" optional="true" mayBeNull="true"&gt;</span>
<span class="rem">/// A JSON object or String containing the querystring for the request.</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;param name="body" type="Object" optional="true" mayBeNull="true"&gt;</span>
<span class="rem">/// A JSON object or String containing the body for the request.</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;returns type="Promise"&gt;</span>
<span class="rem">/// A Promise whose result is an XMLHttpRequest object</span>
<span class="rem">/// &lt;/returns&gt;</span>

<span class="kwrd">var</span> promise = Promise.post(options)
<span class="rem">/// &lt;summary&gt;</span>
<span class="rem">/// Issues an HTTP POST request for the content at the provided url</span>
<span class="rem">/// &lt;/summary&gt;</span>
<span class="rem">/// &lt;param name="options" type="Object"&gt;</span>
<span class="rem">/// An object literal for the arguments "url", "username", "password", </span>
<span class="rem">/// "headers", "query", and "body"</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;returns type="Promise"&gt;</span>
<span class="rem">/// A Promise whose result is an XMLHttpRequest object</span>
<span class="rem">/// &lt;/returns&gt;</span>

<span class="kwrd">var</span> promise = Promise.del(url, username, password, headers, query)
<span class="rem">/// &lt;summary&gt;</span>
<span class="rem">/// Issues an HTTP DELETE request for the content at the provided url</span>
<span class="rem">/// &lt;/summary&gt;</span>
<span class="rem">/// &lt;param name="url" type="String"&gt;The url for the content&lt;/param&gt;</span>
<span class="rem">/// &lt;param name="username" type="String" optional="true" mayBeNull="true"&gt;</span>
<span class="rem">/// The username for the request.</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;param name="password" type="String" optional="true" mayBeNull="true"&gt;</span>
<span class="rem">/// The password for the request.</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;param name="headers" type="Object" optional="true" mayBeNull="true"&gt;</span>
<span class="rem">/// A JSON object containing headers for the request.</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;param name="query" type="Object" optional="true" mayBeNull="true"&gt;</span>
<span class="rem">/// A JSON object or String containing the querystring for the request.</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;returns type="Promise"&gt;</span>
<span class="rem">/// A Promise whose result is an XMLHttpRequest object</span>
<span class="rem">/// &lt;/returns&gt;</span>

<span class="kwrd">var</span> promise = Promise.del(options)
<span class="rem">/// &lt;summary&gt;</span>
<span class="rem">/// Issues an HTTP DELETE request for the content at the provided url</span>
<span class="rem">/// &lt;/summary&gt;</span>
<span class="rem">/// &lt;param name="options" type="Object"&gt;</span>
<span class="rem">/// An object literal for the arguments "url", "username", "password", </span>
<span class="rem">/// "headers", and "query"</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;returns type="Promise"&gt;</span>
<span class="rem">/// A Promise whose result is an XMLHttpRequest object</span>
<span class="rem">/// &lt;/returns&gt;</span>

<span class="kwrd">var</span> promise = Promise.json(method, url, username, password, headers, query, 
                           body)
<span class="rem">/// &lt;summary&gt;</span>
<span class="rem">/// Issues an HTTP request for the content at the provided url, returning it </span>
<span class="rem">/// as a JSON object</span>
<span class="rem">/// &lt;/summary&gt;</span>
<span class="rem">/// &lt;param name="method" type="String"&gt;</span>
<span class="rem">/// The HTTP method to use for the request. May be GET, PUT, POST, or DELETE</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;param name="url" type="String"&gt;The url for the content&lt;/param&gt;</span>
<span class="rem">/// &lt;param name="username" type="String" optional="true" mayBeNull="true"&gt;</span>
<span class="rem">/// The username for the request.</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;param name="password" type="String" optional="true" mayBeNull="true"&gt;</span>
<span class="rem">/// The password for the request.</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;param name="headers" type="Object" optional="true" mayBeNull="true"&gt;</span>
<span class="rem">/// A JSON object containing headers for the request.</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;param name="query" type="Object" optional="true" mayBeNull="true"&gt;</span>
<span class="rem">/// A JSON object or String containing the querystring for the request.</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;param name="body" type="Object" optional="true" mayBeNull="true"&gt;</span>
<span class="rem">/// A JSON object or String containing the body for the request.</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;returns type="Promise"&gt;</span>
<span class="rem">/// A Promise whose result is a JavaScript object</span>
<span class="rem">/// &lt;/returns&gt;</span>

<span class="kwrd">var</span> promise = Promise.json(options)
<span class="rem">/// &lt;summary&gt;</span>
<span class="rem">/// Issues an HTTP request for the content at the provided url, returning it </span>
<span class="rem">/// as a JSON object</span>
<span class="rem">/// &lt;/summary&gt;</span>
<span class="rem">/// &lt;param name="options" type="Object"&gt;</span>
<span class="rem">/// An object literal for the arguments "method", "url", "username", </span>
<span class="rem">/// "password", "headers", "query", and "body"</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;returns type="Promise"&gt;</span>
<span class="rem">/// A Promise whose result is a JavaScript object</span>
<span class="rem">/// &lt;/returns&gt;</span>

<span class="kwrd">var</span> promise = Promise.jsonp(url, query, callbackArg)
<span class="rem">/// &lt;summary&gt;</span>
<span class="rem">/// Issues an HTTP request using JSONP for the content at the provided url</span>
<span class="rem">/// &lt;/summary&gt;</span>
<span class="rem">/// &lt;param name="url" type="String"&gt;The url for the content&lt;/param&gt;</span>
<span class="rem">/// &lt;param name="query" type="Object" optional="true" mayBeNull="true"&gt;</span>
<span class="rem">/// A JSON object or String containing the querystring for the request.</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;param name="callbackArg" type="String" optional="true"&gt;</span>
<span class="rem">/// The name of the callback argument. The default is "callback"</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;returns type="Promise"&gt;</span>
<span class="rem">/// A Promise whose result is a JavaScript object</span>
<span class="rem">/// &lt;/returns&gt;</span>

<span class="kwrd">var</span> promise = Promise.jsonp(options)
<span class="rem">/// &lt;summary&gt;</span>
<span class="rem">/// Issues an HTTP request using JSONP for the content at the provided url</span>
<span class="rem">/// &lt;/summary&gt;</span>
<span class="rem">/// &lt;param name="options" type="Object"&gt;</span>
<span class="rem">/// An object literal for the arguments "url", "query", and "callbackArg"</span>
<span class="rem">/// &lt;/param&gt;</span>
<span class="rem">/// &lt;returns type="Promise"&gt;</span>
<span class="rem">/// A Promise whose result is a JavaScript object</span>
<span class="rem">/// &lt;/returns&gt;</span></pre>]]></content:encoded>
    </item>
    <item>
      <title>Promises and Futures in JavaScript</title>
      <link>https://docs.microsoft.com/archive/blogs/rbuckton/promises-and-futures-in-javascript</link>
      <pubDate>Fri, 29 Jan 2010 12:22:00 GMT</pubDate>
      <dc:creator><![CDATA[Ron Buckton]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/rbuckton/2010/01/29/promises-and-futures-in-javascript/</guid>
      <description><![CDATA[[Note: A new version of Promise.js is available here. It has a less restrictive license and...]]></description>
      <content:encoded><![CDATA[<p><strong>[Note: </strong>A new version of Promise.js is available <a title="Promise.js 2.0" href="https://blogs.msdn.com/b/rbuckton/archive/2011/08/15/promise-js-2-0-promise-framework-for-javascript.aspx">here</a>. It has a less restrictive license and additional functionality. Please be sure to check it out.<strong>]</strong></p>
<p>A <a href="https://en.wikipedia.org/wiki/Promise_(programming)" target="_blank" mce_href="https://en.wikipedia.org/wiki/Promise_(programming)">Promise</a> is a programming model that deals with deferred results in concurrent programming.&nbsp; The basic idea around promises are that rather than issuing a blocking call for a resource (IO, Network, etc.) you can immediately return a <strong>promise</strong> for a future value that will eventually be fulfilled.&nbsp; This allows you to write non-blocking logic that executes asynchronously without having to write a lot of synchronization and plumbing code.</p>
<p>For example, lets say we want to load an RSS feed via HTTP.&nbsp; To accomplish this in JavaScript we have to leverage the XMLHttpRequest object.&nbsp; The following example shows how one might load the RSS feed from this blog using conventional means:</p>
<div class="csharpcode">
<pre><span class="lnum"> 1: </span><span class="kwrd">function</span> fetchSync(url) {</pre>
<pre><span class="lnum"> 2: </span>  <span class="kwrd">var</span> xhr = <span class="kwrd">new</span> XMLHttpRequest();</pre>
<pre><span class="lnum"> 3: </span>  xhr.open(url, <span class="str">"GET"</span>, <span class="kwrd">false</span>, <span class="kwrd">null</span>, <span class="kwrd">null</span>);</pre>
<pre><span class="lnum"> 4: </span>  xhr.send(<span class="kwrd">null</span>);</pre>
<pre><span class="lnum"> 5: </span>  <span class="kwrd">if</span> (xhr.status == 200) {</pre>
<pre><span class="lnum"> 6: </span>    <span class="kwrd">return</span> xhr;</pre>
<pre><span class="lnum"> 7: </span>  }</pre>
<pre><span class="lnum"> 8: </span>  <span class="kwrd">throw</span> <span class="kwrd">new</span> Error(xhr.statusText);</pre>
<pre><span class="lnum"> 9: </span>}</pre>
<pre><span class="lnum"> 10: </span>&nbsp;</pre>
<pre><span class="lnum"> 11: </span><span class="kwrd">function</span> fetchAsync(url, callback, errorCallback) {</pre>
<pre><span class="lnum"> 12: </span>  <span class="kwrd">var</span> xhr = <span class="kwrd">new</span> XMLHttpRequest();</pre>
<pre><span class="lnum"> 13: </span>  xhr.onreadystatechange = <span class="kwrd">function</span>() {</pre>
<pre><span class="lnum"> 14: </span>    <span class="kwrd">if</span> (xhr.readyState == 4) {</pre>
<pre><span class="lnum"> 15: </span>      <span class="kwrd">if</span> (xhr.status == 200) {</pre>
<pre><span class="lnum"> 16: </span>        callback(xhr);</pre>
<pre><span class="lnum"> 17: </span>      }</pre>
<pre><span class="lnum"> 18: </span>      <span class="kwrd">else</span> {</pre>
<pre><span class="lnum"> 19: </span>        errorCallback(<span class="kwrd">new</span> Error(xhr.statusText));</pre>
<pre><span class="lnum"> 20: </span>      }</pre>
<pre><span class="lnum"> 21: </span>    }</pre>
<pre><span class="lnum"> 22: </span>  }</pre>
<pre><span class="lnum"> 23: </span>  xhr.open(url, <span class="str">"GET"</span>, true, <span class="kwrd">null</span>, <span class="kwrd">null</span>);</pre>
<pre><span class="lnum"> 24: </span>  xhr.send(<span class="kwrd">null</span>);</pre>
<pre><span class="lnum"> 25: </span>}</pre>
</div>
<p mce_keep="true">&nbsp;</p>
<p>In the first example, the RSS feed is fetched synchronously (see line 3).&nbsp; In this case the code is straightforward but the request is blocking, which means script execution is suspended until the request is completed or fails.&nbsp; This is not optimal in an AJAX application as it can impact the interactivity of the page.</p>
<p>The second example attempts to alleviate the blocking call by introducing a callback that will be executed when the request completes.&nbsp; This is advantageous as it is non-blocking, however the programming model can become inconsistent if you are working with different asynchronous data sources including loading local resources, performing computationally intensive tasks (such as xml transforms or other data transformation), etc.</p>
<p>To actually use the resulting feed you might have to do some additional work:</p>
<div class="csharpcode">
<pre><span class="lnum"> 1: </span>fetchAsync(</pre>
<pre><span class="lnum"> 2: </span>  <span class="str">"https://blogs.msdn.com/rbuckton/rss.xml"</span>, </pre>
<pre><span class="lnum"> 3: </span>  <span class="kwrd">function</span> (rss) {</pre>
<pre><span class="lnum"> 4: </span>    fetchAsync(</pre>
<pre><span class="lnum"> 5: </span>      <span class="str">"/some/stylesheet.xsl"</span>,</pre>
<pre><span class="lnum"> 6: </span>       <span class="kwrd">function</span> (xsl) {</pre>
<pre><span class="lnum"> 7: </span>         document.getElementById(<span class="str">"host"</span>).innerHTML = rss.responseXML.transformNode(xsl.documentElement);</pre>
<pre><span class="lnum"> 8: </span>       },</pre>
<pre><span class="lnum"> 9: </span>       <span class="kwrd">function</span> (e) {</pre>
<pre><span class="lnum"> 10: </span>         document.getElementById(<span class="str">"host"</span>).innerHTML = <span class="str">"Error: "</span> + ex.message;</pre>
<pre><span class="lnum"> 11: </span>       })</pre>
<pre><span class="lnum"> 12: </span>  },</pre>
<pre><span class="lnum"> 13: </span>  <span class="kwrd">function</span> (ex) {</pre>
<pre><span class="lnum"> 14: </span>    document.getElementById(<span class="str">"host"</span>).innerHTML = <span class="str">"Error: "</span> + ex.message;</pre>
<pre><span class="lnum"> 15: </span>  });</pre>
</div>
<p>In this example we now have two asynchronous calls for content, however one depends on the other and as a result we can&rsquo;t take advantage of concurrent requests to speed up the process.&nbsp;</p>
<p>Now lets look at a concurrent example:</p>
<div class="csharpcode">
<pre><span class="lnum"> 1: </span>var rss = <span class="kwrd">null</span>;</pre>
<pre><span class="lnum"> 2: </span>var xsl = <span class="kwrd">null</span>;</pre>
<pre><span class="lnum"> 3: </span>&nbsp;</pre>
<pre><span class="lnum"> 4: </span>function tryComplete() {</pre>
<pre><span class="lnum"> 5: </span>  <span class="kwrd">if</span> (rss != <span class="kwrd">null</span> &amp;&amp; xsl != <span class="kwrd">null</span>) {</pre>
<pre><span class="lnum"> 6: </span>    document.getElementById(<span class="str">"host"</span>).innerHTML = rss.responseXML.transformNode(xsl.documentElement);</pre>
<pre><span class="lnum"> 7: </span>  }</pre>
<pre><span class="lnum"> 8: </span>}</pre>
<pre><span class="lnum"> 9: </span>&nbsp;</pre>
<pre><span class="lnum"> 10: </span>fetchAsync(</pre>
<pre><span class="lnum"> 11: </span>  <span class="str">"https://blogs.msdn.com/rbuckton/rss.xml"</span>,</pre>
<pre><span class="lnum"> 12: </span>   function(rssXhr) {</pre>
<pre><span class="lnum"> 13: </span>     rss = rssXhr;</pre>
<pre><span class="lnum"> 14: </span>     tryComplete();</pre>
<pre><span class="lnum"> 15: </span>   },</pre>
<pre><span class="lnum"> 16: </span>   function (e) {</pre>
<pre><span class="lnum"> 17: </span>     document.getElementById(<span class="str">"host"</span>).innerHTML += <span class="str">"Error: "</span> + e.message + <span class="str">"&lt;br /&gt;"</span>;</pre>
<pre><span class="lnum"> 18: </span>   });</pre>
<pre><span class="lnum"> 19: </span>&nbsp;</pre>
<pre><span class="lnum"> 20: </span>fetchAsync(</pre>
<pre><span class="lnum"> 21: </span>  <span class="str">"/some/stylesheet.xsl"</span>,</pre>
<pre><span class="lnum"> 22: </span>  function (xslXhr) {</pre>
<pre><span class="lnum"> 23: </span>    xsl = xslXhr;</pre>
<pre><span class="lnum"> 24: </span>    tryComplete();</pre>
<pre><span class="lnum"> 25: </span>  },</pre>
<pre><span class="lnum"> 26: </span>   function (e) {</pre>
<pre><span class="lnum"> 27: </span>     document.getElementById(<span class="str">"host"</span>).innerHTML += <span class="str">"Error: "</span> + e.message + <span class="str">"&lt;br /&gt;"</span>;</pre>
<pre><span class="lnum"> 28: </span>   });</pre>
</div>
<p>Now the above example can utilize concurrent requests and synchronize the results, but wow that&rsquo;s a lot code.</p>
<p>Using promises you can instead do the following:</p>
<div class="csharpcode">
<pre><span class="lnum"> 1: </span><span class="kwrd">var</span> prss = Promise.fetch(<span class="str">"https://blogs.msdn.com/rbuckton/rss.xml"</span>);</pre>
<pre><span class="lnum"> 2: </span><span class="kwrd">var</span> pxsl = Promise.fetch(<span class="str">"/some/stylesheet.xsl"</span>);</pre>
<pre><span class="lnum"> 3: </span>Promise.whenOnly(</pre>
<pre><span class="lnum"> 4: </span>  Promise.join(prss, pxsl),</pre>
<pre><span class="lnum"> 5: </span>  <span class="kwrd">function</span>() {</pre>
<pre><span class="lnum"> 6: </span>    <span class="kwrd">var</span> rss = prss.get_value();</pre>
<pre><span class="lnum"> 7: </span>    <span class="kwrd">var</span> xsl = pxsl.get_value();</pre>
<pre><span class="lnum"> 8: </span>    document.getElementById(<span class="str">"host"</span>).innerHTML = rss.responseXML.transformNode(xsl.responseXML);</pre>
<pre><span class="lnum"> 9: </span>  }, </pre>
<pre><span class="lnum"> 10: </span>  <span class="kwrd">function</span>(ex) {</pre>
<pre><span class="lnum"> 11: </span>    document.getElementById(<span class="str">"host"</span>).innerHTML = <span class="str">"Error: "</span> + ex.message;</pre>
<pre><span class="lnum"> 12: </span>  });</pre>
</div>
<p mce_keep="true">&nbsp;</p>
<p mce_keep="true">&nbsp;</p>
<p>Another feature of Promises is pipelining, the ability to create a series of operations based on the result of promises.&nbsp; The <strong>Promise.when()</strong> function is used to pipeline a promise, creating a new Promise based on the eventual output of the source.&nbsp; For example:</p>
<div class="csharpcode">
<pre><span class="lnum"> 1: </span><span class="kwrd">var</span> pfeed = Promise.fetch(<span class="str">"somefeed.xml"</span>);</pre>
<pre><span class="lnum"> 2: </span>&nbsp;</pre>
<pre><span class="lnum"> 3: </span><span class="kwrd">var</span> pfeedXml = Promise.when(pfeed, <span class="kwrd">function</span>(feed) { <span class="kwrd">return</span> feed.responseXML; });</pre>
<pre><span class="lnum"> 4: </span>Promise.whenOnly(pfeedXml, <span class="kwrd">function</span>(feedXml) { alert(feedXml.xml); });</pre>
<pre><span class="lnum"> 5: </span>&nbsp;</pre>
<pre><span class="lnum"> 6: </span><span class="kwrd">var</span> pfeedText = Promise.when(pfeed, <span class="kwrd">function</span>(feed) { <span class="kwrd">return</span> feed.responseText; });</pre>
<pre><span class="lnum"> 7: </span>Promise.whenOnly(pfeedText, <span class="kwrd">function</span>(feedText) { console.log(feedText); });</pre>
</div>
<p>On line 1 we fetch an xml document from the server.&nbsp; On line 3 we create a pipeline that will eventually convert the response into an XML document.&nbsp; On line 4 when the document is finally available we can alert the user.&nbsp; On line 6 we create a pipeline that will eventually get the response value as text.&nbsp; On line 7 we can log it to the console.</p>
<p>Here&rsquo;s an example of using pipelined Promises to get the public twitter timeline in JSONP:</p>
<div class="csharpcode">
<pre><span class="lnum"> 1: </span>Promise</pre>
<pre><span class="lnum"> 2: </span>  .jsonp(<span class="str">"https://twitter.com/statuses/public_timeline.json"</span>)</pre>
<pre><span class="lnum"> 3: </span>  .whenOnly(<span class="kwrd">function</span>(timeline) {</pre>
<pre><span class="lnum"> 4: </span>    alert(timeline.length);</pre>
<pre><span class="lnum"> 5: </span>  });</pre>
</div>
<p mce_keep="true">&nbsp;</p>
<p>A promise can be created for other deferred actions as well. For example:</p>
<div class="csharpcode">
<pre><span class="lnum"> 1: </span><span class="kwrd">var</span> pinput = <span class="kwrd">new</span> Promise(</pre>
<pre><span class="lnum"> 2: </span>  <span class="kwrd">function</span>(fulfillPromise, breakPromise) {</pre>
<pre><span class="lnum"> 3: </span>    <span class="kwrd">var</span> btn = document.getElementById(<span class="str">"button"</span>);</pre>
<pre><span class="lnum"> 4: </span>    <span class="kwrd">var</span> txt = document.getElementById(<span class="str">"txt"</span>);</pre>
<pre><span class="lnum"> 5: </span>    btn.onclick = <span class="kwrd">function</span>() {</pre>
<pre><span class="lnum"> 6: </span>      fulfillPromise(txt.value);</pre>
<pre><span class="lnum"> 7: </span>    }</pre>
<pre><span class="lnum"> 8: </span>  }</pre>
<pre><span class="lnum"> 9: </span>);</pre>
<pre><span class="lnum"> 10: </span>&nbsp;</pre>
<pre><span class="lnum"> 11: </span>pinput.whenOnly(<span class="kwrd">function</span>(value) { alert(value); });</pre>
</div>
<p mce_keep="true">&nbsp;</p>
<p>The above sample creates a promise for eventual input that you can act on at any point.</p>
<p>Whether a promise completes after a delay or very quickly (even synchronously), the programming model doesn&rsquo;t change.&nbsp; The Promise model can even handle present information, so that present and future data can be mixed within the model.&nbsp; This is due to <strong>Promise.immediate()</strong>, which creates a promise that is fulfilled synchronously.&nbsp; All of the &ldquo;static&rdquo; methods on the <strong>Promise</strong> object will implicitly create a Promise for any non-future data (data that is not already encapsulated in a <strong>Promise</strong>).</p>
<p>Here&rsquo;s an example of a future factorial (based on the Wikipedia example):</p>
<div class="csharpcode">
<pre><span class="lnum"> 1: </span><span class="kwrd">function</span> factorial(value) {</pre>
<pre><span class="lnum"> 2: </span>  <span class="kwrd">return</span> <span class="kwrd">new</span> Promise(</pre>
<pre><span class="lnum"> 3: </span>    <span class="kwrd">function</span>(fulfillPromise, breakPromise) {</pre>
<pre><span class="lnum"> 4: </span>      setTimeout(</pre>
<pre><span class="lnum"> 5: </span>        <span class="kwrd">function</span>() {</pre>
<pre><span class="lnum"> 6: </span>          <span class="kwrd">var</span> result = 0;</pre>
<pre><span class="lnum"> 7: </span>          <span class="kwrd">do</span> {</pre>
<pre><span class="lnum"> 8: </span>            result += value;</pre>
<pre><span class="lnum"> 9: </span>          }</pre>
<pre><span class="lnum"> 10: </span>          <span class="kwrd">while</span> (--value &gt; 0);</pre>
<pre><span class="lnum"> 11: </span>          fulfillPromise(result);</pre>
<pre><span class="lnum"> 12: </span>        },</pre>
<pre><span class="lnum"> 13: </span>        1);</pre>
<pre><span class="lnum"> 14: </span>    }</pre>
<pre><span class="lnum"> 15: </span>  );</pre>
<pre><span class="lnum"> 16: </span>}</pre>
<pre><span class="lnum"> 17: </span>&nbsp;</pre>
<pre><span class="lnum"> 18: </span><span class="kwrd">var</span> pfactorial = factorial(100000)</pre>
<pre><span class="lnum"> 19: </span>  .when(<span class="kwrd">function</span>(result) { <span class="kwrd">return</span> result + 3; })</pre>
<pre><span class="lnum"> 20: </span>  .whenOnly(<span class="kwrd">function</span>(result) { alert(result); });</pre>
</div>
<p>This example uses setTimeout (at line 4) to ensure the request returns immediately and does not block linear execution of the code.</p>
<p>*NOTE: The attached API does not overcome the Same Origin Policy when used in the browser.&nbsp; This means that you can only make requests back to the same domain as the caller.&nbsp; Same Origin Policy does not apply for Gadgets (Windows 7 and Windows Vista) or for Widgets (Windows Mobile 6.5), which is where I&rsquo;ve used this library for the most part. I have added some JSONP support in the library however JSONP is very limited.</p>
<p>Here is a quick overview of the current Promise API:</p>
<pre class="csharpcode"><span class="rem">// constructor</span>

<span class="kwrd">var</span> p = <span class="kwrd">new</span> Promise(initCallback) 
<span class="rem">// initCallback: callback function that takes two </span>
<span class="rem">// parameters, the fulfillPromise and breakPromise </span>
<span class="rem">// callback functions.</span>

<span class="rem">// members</span>

p.get_isComplete() 
<span class="rem">// Gets whether the promise is complete</span>
<span class="rem">// returns: Boolean value that is True if the promise is </span>
<span class="rem">// complete</span>

p.get_value()
<span class="rem">// Gets the value of the promise or 'undefined' if the </span>
<span class="rem">// promise has not completed. If the promise was </span>
<span class="rem">// broken during execution an exception will be thrown</span>
<span class="rem">// returns: Object value </span>

p.call(name, params)
<span class="rem">// Calls a named function on the future value of the </span>
<span class="rem">// promise</span>
<span class="rem">// name: String value for name of the field on the </span>
<span class="rem">// promise result object that contains a function </span>
<span class="rem">// to call</span>
<span class="rem">// params: parameter array of arguments to the </span>
<span class="rem">// function. specified as in-line arguments not as an</span>
<span class="rem">// array: p.call("foo", 1, 2, 3)</span>
<span class="rem">// returns: a promise for the result of the call</span>

p.getValue(name)
<span class="rem">// Gets the value of a named field on the future</span>
<span class="rem">// value of the promise</span>
<span class="rem">// name: String value for the name of a field on the</span>
<span class="rem">// promise result object</span>
<span class="rem">// returns: a promise for the value of the field</span>

p.setValue(name, value)
<span class="rem">// Sets the value of a named field on the future</span>
<span class="rem">// value of the promise</span>
<span class="rem">// name: String value for the name of a field on the</span>
<span class="rem">// promise result object</span>
<span class="rem">// value: Object value to set on the field for the</span>
<span class="rem">// promise result object</span>
<span class="rem">// returns: none</span>

p.when(fulfillPromise, breakPromise, context)
<span class="rem">// Creates a promise for the value of an action taken</span>
<span class="rem">// on the future value of the promise</span>
<span class="rem">// fulfillPromise: Function that takes the value of the</span>
<span class="rem">// promise when it completes and is used to act</span>
<span class="rem">// on the future value. The result is used as the </span>
<span class="rem">// value of the new promise</span>
<span class="rem">// breakPromise: Function that takes the exception</span>
<span class="rem">// raised by the promise when it fails and is used</span>
<span class="rem">// to act on the failure. The result is used as the</span>
<span class="rem">// value of the new promise</span>
<span class="rem">// context: Optional Object to use as the 'this' value</span>
<span class="rem">// for the fulfillPromise or breakPromise callbacks</span>
<span class="rem">// returns: a Promise for the result of actions taken</span>
<span class="rem">// in fulfillPromise or breakPromise</span>

p.whenOnly(fulfillPromise, breakPromise, context)
<span class="rem">// Enqueues an action to be taken on the future </span>
<span class="rem">// value of the promise</span>
<span class="rem">// fulfillPromise: Function that takes the value of the</span>
<span class="rem">// promise when it completes and is used to act</span>
<span class="rem">// on the future value. </span>
<span class="rem">// breakPromise: Function that takes the exception</span>
<span class="rem">// raised by the promise when it fails and is used</span>
<span class="rem">// to act on the failure. </span>
<span class="rem">// context: Optional object to use as the 'this' value</span>
<span class="rem">// for the fulfillPromise or breakPromise callbacks</span>
<span class="rem">// returns: none</span>

p.join(promises)
<span class="rem">// Creates a new promise that completes when all</span>
<span class="rem">// joined promises have completed</span>
<span class="rem">// promises: Parameter array of other promises</span>
<span class="rem">// returns: a new Promise</span>


<span class="rem">// static/type members</span>

Promise.when(promise, fulfillPromise, breakPromise, context)
<span class="rem">// Creates a promise for the value of an action taken</span>
<span class="rem">// on the future value of the promise</span>
<span class="rem">// promise: The promise on which to act</span>
<span class="rem">// fulfillPromise: Function that takes the value of the</span>
<span class="rem">// promise when it completes and is used to act</span>
<span class="rem">// on the future value. The result is used as the </span>
<span class="rem">// value of the new promise</span>
<span class="rem">// breakPromise: Function that takes the exception</span>
<span class="rem">// raised by the promise when it fails and is used</span>
<span class="rem">// to act on the failure. The result is used as the</span>
<span class="rem">// value of the new promise</span>
<span class="rem">// context: Optional Object to use as the 'this' value</span>
<span class="rem">// for the fulfillPromise or breakPromise callbacks</span>
<span class="rem">// returns: a Promise for the result of actions taken</span>
<span class="rem">// in fulfillPromise or breakPromise</span>

Promise.whenOnly(promise, fulfillPromise, breakPromise, context)
<span class="rem">// Enqueues an action to be taken on the future </span>
<span class="rem">// value of the promise</span>
<span class="rem">// promise: The promise on which to act</span>
<span class="rem">// fulfillPromise: Function that takes the value of the</span>
<span class="rem">// promise when it completes and is used to act</span>
<span class="rem">// on the future value. </span>
<span class="rem">// breakPromise: Function that takes the exception</span>
<span class="rem">// raised by the promise when it fails and is used</span>
<span class="rem">// to act on the failure. </span>
<span class="rem">// context: Optional object to use as the 'this' value</span>
<span class="rem">// for the fulfillPromise or breakPromise callbacks</span>
<span class="rem">// returns: none</span>

Promise.join(promises)
<span class="rem">// Creates a new promise that completes when all</span>
<span class="rem">// joined promises have completed</span>
<span class="rem">// promises: Parameter array of other promises</span>
<span class="rem">// returns: a new Promise</span>

Promise.make(value)
<span class="rem">// Makes a promise on a value. If the value is a promise it </span>
<span class="rem">// is returned. If the value is not a promise an immediate</span>
<span class="rem">// promise is returned</span>
<span class="rem">// value: an Object that may or may not be a promise</span>
<span class="rem">// returns: a Promise for the value</span>

Promise.broken(exception)
<span class="rem">// Makes a promise that is immediately broken</span>
<span class="rem">// exception: The error for the promise</span>
<span class="rem">// returns: a broken Promise for the exception</span>

Promise.immediate(value)
<span class="rem">// Makes a promise that is immediately fulfilled</span>
<span class="rem">// value: The value for the promise</span>
<span class="rem">// returns: a fulfilled Promise for the value</span>

Promise.fetch(url, method, username, password, headers, query, body)
<span class="rem">// Creates a Promise for a completed XMLHttpRequest for the </span>
<span class="rem">// requested resource</span>
<span class="rem">// url: String value for the url</span>
<span class="rem">// method: Optional string value for the method. default is "GET"</span>
<span class="rem">// username: Optional string value for the username for Basic </span>
<span class="rem">// Authentication. default is 'null'</span>
<span class="rem">// password: Optional string value for the password for Basic</span>
<span class="rem">// Authentication. default is 'null'</span>
<span class="rem">// headers: Optional Object containing name/value pairs for </span>
<span class="rem">// HTTP headers. default is 'null'</span>
<span class="rem">// query: Optional Object or String containing name/value pairs</span>
<span class="rem">// to be added to the url as a querystring. default is 'null'</span>
<span class="rem">// body: Optional Object or String containing the request</span>
<span class="rem">// body for the request. A String is sent as-is while an Object</span>
<span class="rem">// contains name/value pairs that are url form encoded. </span>
<span class="rem">// default is null</span>
<span class="rem">// returns: A Promise for the completed XMLHttpRequest</span>

Promise.json(url, method, username, password, headers, query, body)
<span class="rem">// Creates a Promise for a JSON object parsed from the result of an </span>
<span class="rem">// XMLHttpRequest for the requested resource.</span>
<span class="rem">// This requires the JSON object which is Native in IE8. If you </span>
<span class="rem">// wish to use this method on a browser that does not have the</span>
<span class="rem">// native JSON object, please download www.json.org/json2.js</span>
<span class="rem">// url: String value for the url</span>
<span class="rem">// method: Optional string value for the method. default is "GET"</span>
<span class="rem">// username: Optional string value for the username for Basic </span>
<span class="rem">// Authentication. default is 'null'</span>
<span class="rem">// password: Optional string value for the password for Basic</span>
<span class="rem">// Authentication. default is 'null'</span>
<span class="rem">// headers: Optional Object containing name/value pairs for </span>
<span class="rem">// HTTP headers. default is 'null'</span>
<span class="rem">// query: Optional Object or String containing name/value pairs</span>
<span class="rem">// to be added to the url as a querystring. default is 'null'</span>
<span class="rem">// body: Optional Object or String containing the request</span>
<span class="rem">// body for the request. A String is sent as-is while an Object</span>
<span class="rem">// contains name/value pairs that are url form encoded. </span>
<span class="rem">// default is null</span>
<span class="rem">// returns: A Promise for the JSON value of the response</span>

Promise.jsonp(url, query, callbackArg)
<span class="rem">// Uses JSONP to request a JSON resource</span>
<span class="rem">// url: String value for the url</span>
<span class="rem">// query: Optional Object or String containing name/value pairs</span>
<span class="rem">// to be added to the url as a querystring. default is 'null'</span>
<span class="rem">// callbackArg: Optional string that specifies the name of</span>
<span class="rem">// a querystring argument used to hold the name of</span>
<span class="rem">// a callback function. default is "callback"</span></pre>
<p>Promise.js is licensed under the MSR-LA for non-commercial use only. The license is included in license.txt in the zip.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Components.PostAttachments/00/09/94/81/48/promise.zip" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-09-94-81-48/promise.zip">promise.zip</a></p>]]></content:encoded>
    </item>
    <item>
      <title>TFS Walkthrough Series: Part 3 - Opening the Source Control Explorer</title>
      <link>https://docs.microsoft.com/archive/blogs/rbuckton/tfs-walkthrough-series-part-3-opening-the-source-control-explorer</link>
      <pubDate>Mon, 07 Sep 2009 08:43:00 GMT</pubDate>
      <dc:creator><![CDATA[Ron Buckton]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/rbuckton/2009/09/07/tfs-walkthrough-series-part-3-opening-the-source-control-explorer/</guid>
      <description><![CDATA[Open Microsoft Visual Studio 2008 
Ensure you have an active connection to Team Foundation Server...]]></description>
      <content:encoded><![CDATA[<OL>
<LI>Open Microsoft Visual Studio 2008 </LI>
<LI>Ensure you have an active connection to Team Foundation Server (see <EM>Walkthrough: <A href="https://blogs.msdn.com/rbuckton/archive/2009/09/06/tfs-walkthrough-series-part-1-connecting-to-team-foundation-server.aspx" mce_href="https://blogs.msdn.com/rbuckton/archive/2009/09/06/tfs-walkthrough-series-part-1-connecting-to-team-foundation-server.aspx">Connecting to Team Foundation Server</A></EM>) </LI>
<LI>In the "Team Explorer" task pane, expand the Team Project </LI>
<LI>
<DIV>Double-click on the <STRONG>Source Control</STRONG> folder. </DIV>
<P><IMG alt="" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/rbuckton/090509_1243_TFSWalkthro1.png" original-url="https://blogs.msdn.com/blogfiles/rbuckton/090509_1243_TFSWalkthro1.png" mce_src="https://blogs.msdn.com/blogfiles/rbuckton/090509_1243_TFSWalkthro1.png"> </P>
<P><SPAN style="FONT-FAMILY: Arial Narrow; FONT-SIZE: 8pt">Figure 8 - Source Control Explorer </SPAN></P></LI></OL>]]></content:encoded>
    </item>
    <item>
      <title>TFS Walkthrough Series: Part 2 - Viewing Work Items</title>
      <link>https://docs.microsoft.com/archive/blogs/rbuckton/tfs-walkthrough-series-part-2-viewing-work-items</link>
      <pubDate>Sun, 06 Sep 2009 12:42:00 GMT</pubDate>
      <dc:creator><![CDATA[Ron Buckton]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/rbuckton/2009/09/06/tfs-walkthrough-series-part-2-viewing-work-items/</guid>
      <description><![CDATA[Open Microsoft Visual Studio 2008 
Ensure you have an active connection to Team Foundation Server...]]></description>
      <content:encoded><![CDATA[<OL>
<LI>Open Microsoft Visual Studio 2008 </LI>
<LI>Ensure you have an active connection to Team Foundation Server (see <EM>Walkthrough: <A href="https://blogs.msdn.com/rbuckton/archive/2009/09/06/tfs-walkthrough-series-part-1-connecting-to-team-foundation-server.aspx" mce_href="https://blogs.msdn.com/rbuckton/archive/2009/09/06/tfs-walkthrough-series-part-1-connecting-to-team-foundation-server.aspx">Connecting to Team Foundation Server</A></EM>) </LI>
<LI>
<DIV>In the "Team Explorer" task pane, expand the Team Project (in this example: <STRONG><EM>TeamProject</EM></STRONG>) to the following folder: <STRONG><EM>TeamProject</EM> \ Work Items \ Team Queries</STRONG> </DIV>
<P><IMG alt="" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/rbuckton/090509_1242_TFSWalkthro1.png" original-url="https://blogs.msdn.com/blogfiles/rbuckton/090509_1242_TFSWalkthro1.png" mce_src="https://blogs.msdn.com/blogfiles/rbuckton/090509_1242_TFSWalkthro1.png"> </P>
<P><SPAN style="FONT-FAMILY: Arial Narrow; FONT-SIZE: 8pt">Figure 6 - Work Item Queries </SPAN></P></LI>
<LI>
<DIV>Double-click on a Team Query. This will open the list of work items that match the query. </DIV>
<P><IMG alt="" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/rbuckton/090509_1242_TFSWalkthro2.png" original-url="https://blogs.msdn.com/blogfiles/rbuckton/090509_1242_TFSWalkthro2.png" mce_src="https://blogs.msdn.com/blogfiles/rbuckton/090509_1242_TFSWalkthro2.png"> </P>
<P><SPAN style="FONT-FAMILY: Arial Narrow; FONT-SIZE: 8pt">Figure 7 - Example Work Item Query </SPAN></P></LI>
<LI>Review or make any necessary changes and click <STRONG>Save</STRONG> (from the File menu or the disk icon, or press <STRONG>Ctrl+S</STRONG>) to update the server. </LI></OL>]]></content:encoded>
    </item>
    <item>
      <title>TFS Walkthrough Series: Part 1 - Connecting to Team Foundation Server</title>
      <link>https://docs.microsoft.com/archive/blogs/rbuckton/tfs-walkthrough-series-part-1-connecting-to-team-foundation-server</link>
      <pubDate>Sun, 06 Sep 2009 08:14:00 GMT</pubDate>
      <dc:creator><![CDATA[Ron Buckton]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/rbuckton/2009/09/06/tfs-walkthrough-series-part-1-connecting-to-team-foundation-server/</guid>
      <description><![CDATA[Open Microsoft Visual Studio 2008 
In Visual Studio 2008, click the menu: Tools / Connect to Team...]]></description>
      <content:encoded><![CDATA[<OL>
<LI>Open Microsoft Visual Studio 2008 </LI>
<LI>In Visual Studio 2008, click the menu: <STRONG>Tools / Connect to Team Foundation Server</STRONG> </LI>
<LI>
<DIV>In the "Connect to Team Foundation Server" dialog, click the button: <STRONG>Servers…</STRONG> </DIV>
<P><IMG alt="" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/rbuckton/090509_1241_TFSWalkthro1.png" original-url="https://blogs.msdn.com/blogfiles/rbuckton/090509_1241_TFSWalkthro1.png" mce_src="https://blogs.msdn.com/blogfiles/rbuckton/090509_1241_TFSWalkthro1.png"> </P>
<P><SPAN style="FONT-FAMILY: Arial Narrow; FONT-SIZE: 8pt">Figure 3 - Connecting to a Team Foundation Server </SPAN></P></LI>
<LI>
<DIV>In the "Add/Remove Team Foundation Server" dialog, click the button: <STRONG>Add…</STRONG> </DIV>
<P><IMG alt="" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/rbuckton/090509_1241_TFSWalkthro2.png" original-url="https://blogs.msdn.com/blogfiles/rbuckton/090509_1241_TFSWalkthro2.png" mce_src="https://blogs.msdn.com/blogfiles/rbuckton/090509_1241_TFSWalkthro2.png"> </P>
<P><SPAN style="FONT-FAMILY: Arial Narrow; FONT-SIZE: 8pt">Figure 4 - Managing the list of Team Foundation Servers </SPAN></P></LI>
<LI>
<DIV>In the "Add Team Foundation Server" dialog, enter the server name and click the button: <STRONG>OK</STRONG> </DIV>
<P><IMG alt="" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/rbuckton/090509_1241_TFSWalkthro3.png" original-url="https://blogs.msdn.com/blogfiles/rbuckton/090509_1241_TFSWalkthro3.png" mce_src="https://blogs.msdn.com/blogfiles/rbuckton/090509_1241_TFSWalkthro3.png"> </P>
<P><SPAN style="FONT-FAMILY: Arial Narrow; FONT-SIZE: 8pt">Figure 5 - Adding a Team Foundation Server </SPAN></P></LI>
<LI>In the "Add/Remove Team Foundation Server" dialog, click the button: <STRONG>Close</STRONG> </LI>
<LI>In the "Connect to Team Foundation Server" dialog, check each of the projects you wish to view and click: <STRONG>OK</STRONG> </LI>
<LI>
<DIV>The "Team Explorer" tool pane should open for you to browse the Team Project. </DIV>
<P><IMG alt="" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/rbuckton/090509_1241_TFSWalkthro4.png" original-url="https://blogs.msdn.com/blogfiles/rbuckton/090509_1241_TFSWalkthro4.png" mce_src="https://blogs.msdn.com/blogfiles/rbuckton/090509_1241_TFSWalkthro4.png"> </P></LI></OL>]]></content:encoded>
    </item>
    <item>
      <title>Team Foundation Server Walkthrough Series: Introduction</title>
      <link>https://docs.microsoft.com/archive/blogs/rbuckton/team-foundation-server-walkthrough-series-introduction</link>
      <pubDate>Sat, 05 Sep 2009 08:38:53 GMT</pubDate>
      <dc:creator><![CDATA[Ron Buckton]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/rbuckton/2009/09/05/team-foundation-server-walkthrough-series-introduction/</guid>
      <description><![CDATA[The following is a series of walkthroughs for Microsoft Visual Studio 2008 Team Foundation Server....]]></description>
      <content:encoded><![CDATA[<p>The following is a series of walkthroughs for Microsoft Visual Studio 2008 Team Foundation Server.  They range from simply making a TFS connection to setting up build configurations and branching scenarios.
</p><ul><li>Connecting to Team Foundation Server
</li><li>Viewing Work Items
</li><li>Opening the Source Control Explorer
</li><li>Creating Workspaces
</li><li>Checking in Pending Changes
</li><li>Creating a DEVELOPMENT branch
</li><li>Creating a PRODUCTION branch
</li><li>Forward Integration from MAIN to DEVELOPMENT
</li><li>Forward Integration from MAIN to PRODUCTION
</li><li>Reverse Integration from DEVELOPMENT to MAIN
</li><li>Creating a Build Definition
</li><li>Queuing a Build
</li><li>Managing Build Quality
</li><li>Fixing issues in a PRODUCTION release
</li><li>Performing a Baseless Merge
</li><li>Sample Peer Code Review Process using Shelvesets</li></ul>]]></content:encoded>
    </item>
    <item>
      <title>TFS Quick Tips: #1 Adding a screenshot to a work item</title>
      <link>https://docs.microsoft.com/archive/blogs/rbuckton/tfs-quick-tips-1-adding-a-screenshot-to-a-work-item</link>
      <pubDate>Wed, 23 Jul 2008 14:43:10 GMT</pubDate>
      <dc:creator><![CDATA[Ron Buckton]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/rbuckton/2008/07/23/tfs-quick-tips-1-adding-a-screenshot-to-a-work-item/</guid>
      <description><![CDATA[The Team Explorer in Visual Studio provides a quick (and not exactly obvious) method for attaching a...]]></description>
      <content:encoded><![CDATA[<p>The Team Explorer in Visual Studio provides a quick (and not exactly obvious) method for attaching a screenshot or other content to a Work Item.</p>  <h4>Screenshots</h4>  <p>To quickly add a screenshot do the following:</p>  <p>1. Press PrtScrn or Alt+PrntScrn (Captures only the currently active window)</p>  <p>2. Open a Work Item (Bug, Task, etc) in team explorer</p>  <p>3. Click &#8220;File Attachments&#8221;</p>  <p>4. Press Ctrl+V (Paste)</p>  <p>A file called &#8220;Screenshot.png&#8221; is automatically attached to the work item.</p>  <h4>Copied Text</h4>  <p>To quickly add any copied text as an attachment to a work item do the following:</p>  <p>1. Select the text to copy (or press Ctrl+A to select all text in the active input area like a page or document)</p>  <p>2. Open a Work Item (Bug, Task, etc) in team explorer</p>  <p>3. Click &#8220;File Attachments&#8221;</p>  <p>4. Press Ctrl+V (Paste)</p>  <p>A file called &#8220;PastedText.txt&#8221; is automatically attached to the work item.</p>  <h4>Copied Files</h4>  <p>You can also quickly add a file from your desktop as an attachment using the same steps as above:</p>  <p>1. Select the files to copy</p>  <p>2. Open a Work Item (Bug, Task, etc) in team explorer</p>  <p>3. Click &#8220;File Attachments&#8221;</p>  <p>4. Press Ctrl+V (Paste)</p>  <p>Each of the files selected is now attached to the work item.</p>  <h4>Bonus Tip &#8211; Copy and Paste Text from an Alert</h4>  <p>If you get an alert in a page like so:</p>  <p><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="126" alt="clip_image002" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/rbuckton/WindowsLiveWriter/TFSQuickTips1Addingascreenshottoaworkite_CEFC/clip_image002_3.jpg" original-url="https://blogs.msdn.com/blogfiles/rbuckton/WindowsLiveWriter/TFSQuickTips1Addingascreenshottoaworkite_CEFC/clip_image002_3.jpg" width="189" border="0" /></p>  <p>Simply press Ctrl+C (Copy) to copy the contents of the dialog into the clipboard. To paste the text you can just use Ctrl+V:</p>  <p>---------------------------</p>  <p>Windows Internet Explorer</p>  <p>---------------------------</p>  <p>You can copy this</p>  <p>---------------------------</p>  <p>OK</p>  <p>---------------------------</p>]]></content:encoded>
    </item>
    <item>
      <title>"Wheel of Time" author James Oliver Rigney, Jr. aka "Robert Jordan" passes away at 58</title>
      <link>https://docs.microsoft.com/archive/blogs/rbuckton/wheel-of-time-author-james-oliver-rigney-jr-aka-robert-jordan-passes-away-at-58</link>
      <pubDate>Mon, 17 Sep 2007 13:54:28 GMT</pubDate>
      <dc:creator><![CDATA[Ron Buckton]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/rbuckton/2007/09/17/wheel-of-time-author-james-oliver-rigney-jr-aka-robert-jordan-passes-away-at-58/</guid>
      <description><![CDATA[From the official website:  New York Times #1 best-selling author Robert Jordan passed away on...]]></description>
      <content:encoded><![CDATA[<p>From the official website:</p> <blockquote> <p><i>New York Times</i> #1 best-selling author Robert Jordan passed away on Sunday September 16th at 2:45 PM EST. His passing was announced by his cousin Wilson on his official blog, hosted <a href="https://www.dragonmount.com/" target="_blank">here</a>.<br>[<a title="https://www.dragonmount.com/" href="https://www.dragonmount.com/">https://www.dragonmount.com/</a>]</p></blockquote> <p>I've been reading Robert Jordan's novels for a long time and have all of the available "Wheel of Time" books featured prominently on my bookshelves at home.&nbsp; His fantasy writings were complex and emotional, weaving together the lives of many characters through dark and trying times.&nbsp; He died before completing the 12th and final volume of the "Wheel of Time" series although currently it is believed that enough of the final volume has been penned to be able to complete the series, although the exact time frame for the final volume is still unknown.&nbsp; </p> <p>The story is on <a href="https://www.cnn.com/2007/SHOWBIZ/books/09/17/obit.jordan.ap/index.html?iref=newssearch" target="_blank">CNN</a> and additional information is available at the following fan sites:</p> <li><a href="https://www.wotmania.com">wotmania.com</a> <li><a href="https://www.tarvalon.net">TarValon.net</a> <li><a href="https://www.theoryland.com">Theoryland.com</a></li>]]></content:encoded>
    </item>
    <item>
      <title>Visual Studio "Browse with..." multiple browsers</title>
      <link>https://docs.microsoft.com/archive/blogs/rbuckton/visual-studio-browse-with-multiple-browsers</link>
      <pubDate>Wed, 12 Sep 2007 11:41:14 GMT</pubDate>
      <dc:creator><![CDATA[Ron Buckton]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/rbuckton/2007/09/12/visual-studio-browse-with-multiple-browsers/</guid>
      <description><![CDATA[Here's a tip if you're doing a lot of cross browser ASP.NET or AJAX development in Visual Studio:...]]></description>
      <content:encoded><![CDATA[<p>Here's a tip if you're doing a lot of cross browser ASP.NET or AJAX development in Visual Studio:</p> <ul> <li>Right click an .aspx file and choose "Browse with..."<br><br><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="241" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/rbuckton/WindowsLiveWriter/VisualStudioBrowsewith.multiplebrowsers_A43A/image_3.png" original-url="https://blogs.msdn.com/blogfiles/rbuckton/WindowsLiveWriter/VisualStudioBrowsewith.multiplebrowsers_A43A/image_3.png" width="320" border="0"> <br> <li>If you're like me you've probably added some additional browsers to your "Browse with" list like FireFox, Opera and Safari.&nbsp; If you want to view the page in multiple browsers, CTRL+click each item:<br><br><img height="242" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/rbuckton/WindowsLiveWriter/VisualStudioBrowsewith.multiplebrowsers_A43A/image_8.png" original-url="https://blogs.msdn.com/blogfiles/rbuckton/WindowsLiveWriter/VisualStudioBrowsewith.multiplebrowsers_A43A/image_8.png" width="320" border="0"> <br> <li>Hit "Browse" and all of the browsers will open for the specified page.  <li>If you want to open multiple browsers <strong>every</strong> time, click "Set as Default":<br><br><img height="241" alt="image" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/rbuckton/WindowsLiveWriter/VisualStudioBrowsewith.multiplebrowsers_A43A/image_11.png" original-url="https://blogs.msdn.com/blogfiles/rbuckton/WindowsLiveWriter/VisualStudioBrowsewith.multiplebrowsers_A43A/image_11.png" width="320" border="0"> <br> <li>Now all of the browsers will open whenever you choose "Browse" from the context menu.</li></ul>]]></content:encoded>
    </item>
    <item>
      <title>DOM Event inconsistencies between browsers</title>
      <link>https://docs.microsoft.com/archive/blogs/rbuckton/dom-event-inconsistencies-between-browsers</link>
      <pubDate>Tue, 11 Sep 2007 16:48:33 GMT</pubDate>
      <dc:creator><![CDATA[Ron Buckton]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/rbuckton/2007/09/11/dom-event-inconsistencies-between-browsers/</guid>
      <description><![CDATA[I've been working on some bugs in the Calendar extender from the ASP.NET AJAX Control Toolkit and...]]></description>
      <content:encoded><![CDATA[<p>I've been working on some bugs in the <a href="https://ajax.asp.net/ajaxtoolkit/calendar" target="_blank">Calendar</a> extender from the <a href="https://ajax.asp.net/ajaxtoolkit" target="_blank">ASP.NET AJAX Control Toolkit</a> and have been resolving some of the focus/blur events.&nbsp; I've been trying to make the calendar work consistently across all of the browsers and found some frustrating differences in event firing order between the browsers.</p> <p>Here are a list of some of the DOM events supported by the various browsers I tested:</p> <p>&nbsp;</p> <h5></h5> <h4>Table 1 - DOM Events by Browser</h4> <table cellspacing="0" cellpadding="2" width="418" border="1"> <tbody> <tr> <td width="122">Event</td> <td align="middle" width="69">DOM Level</td> <td align="middle" width="53">IE</td> <td align="middle" width="55">FF</td> <td align="middle" width="56">OP</td> <td align="middle" width="61">SF</td></tr> <tr> <td width="122">DOMActivate</td> <td align="middle" width="69">Level 2</td> <td align="middle" width="53">&nbsp;</td> <td align="middle" width="55">&nbsp;</td> <td align="middle" width="56">&nbsp;</td> <td align="middle" width="61">*</td></tr> <tr> <td width="122">activate</td> <td align="middle" width="69"><sup><i>2</i></sup></td> <td align="middle" width="53">*</td> <td align="middle" width="55">&nbsp;</td> <td align="middle" width="56">&nbsp;</td> <td align="middle" width="61">&nbsp;</td></tr> <tr> <td width="122">DOMFocusIn</td> <td align="middle" width="69">Level 2</td> <td align="middle" width="53">&nbsp;</td> <td align="middle" width="55">&nbsp;</td> <td align="middle" width="56"><sup><i>1</i></sup></td> <td align="middle" width="61"><sup><i>1</i></sup></td></tr> <tr> <td width="122">focusin</td> <td align="middle" width="69"><sup><i>2</i></sup></td> <td align="middle" width="53">*</td> <td align="middle" width="55">&nbsp;</td> <td align="middle" width="56">&nbsp;</td> <td align="middle" width="61">&nbsp;</td></tr> <tr> <td width="122">focus</td> <td align="middle" width="69">Level 0</td> <td align="middle" width="53">*</td> <td align="middle" width="55"><sup><i>1</i></sup></td> <td align="middle" width="56"><sup><i>1</i></sup></td> <td align="middle" width="61"><sup><i>1</i></sup></td></tr> <tr> <td width="122">DOMDeactivate</td> <td align="middle" width="69">Level 2</td> <td align="middle" width="53">&nbsp;</td> <td align="middle" width="55">&nbsp;</td> <td align="middle" width="56">&nbsp;</td> <td align="middle" width="61">&nbsp;</td></tr> <tr> <td width="122">deactivate</td> <td align="middle" width="69"><sup><i>2</i></sup></td> <td align="middle" width="53">*</td> <td align="middle" width="55">&nbsp;</td> <td align="middle" width="56">&nbsp;</td> <td align="middle" width="61">&nbsp;</td></tr> <tr> <td width="122">DOMFocusOut</td> <td align="middle" width="69">Level 2</td> <td align="middle" width="53">&nbsp;</td> <td align="middle" width="55">&nbsp;</td> <td align="middle" width="56"><sup><i>1</i></sup></td> <td align="middle" width="61"><sup><i>1</i></sup></td></tr> <tr> <td width="122">focusout</td> <td align="middle" width="69"><sup><i>2</i></sup></td> <td align="middle" width="53">*</td> <td align="middle" width="55">&nbsp;</td> <td align="middle" width="56">&nbsp;</td> <td align="middle" width="61">&nbsp;</td></tr> <tr> <td width="122">blur</td> <td align="middle" width="69">Level 0</td> <td align="middle" width="53">*</td> <td align="middle" width="55"><sup><i>1</i></sup></td> <td align="middle" width="56"><sup><i>1</i></sup></td> <td align="middle" width="61"><sup><i>1</i></sup></td></tr> <tr> <td width="122">mousedown</td> <td align="middle" width="69">Level 0</td> <td align="middle" width="53">*</td> <td align="middle" width="55">*</td> <td align="middle" width="56">*</td> <td align="middle" width="61">*</td></tr> <tr> <td width="122">mouseup</td> <td align="middle" width="69">Level 0</td> <td align="middle" width="53">*</td> <td align="middle" width="55">*</td> <td align="middle" width="56">*</td> <td align="middle" width="61">*</td></tr> <tr> <td width="122">click</td> <td align="middle" width="69">Level 0</td> <td align="middle" width="53">*</td> <td align="middle" width="55">*</td> <td align="middle" width="56">*</td> <td align="middle" width="61">*</td></tr></tbody></table> <p style="font-size: x-small"><i>IE: Internet Explorer 7.0<br>FF: Firefox 2.0.0.6<br>OP: Opera 9.23<br>SF: Safari 3.03 Beta (Windows)<br>*: Implemented on any element<br>1: Implemented only on specific elements<br>2: IE-only implementation<br></i></p> <p>&nbsp;</p> <p>Internet Explorer uses activate/focusin/focusout instead of DOMActivate/DOMFocusIn/DOMFocusOut for events.&nbsp; Interestingly only IE and Safari support DOMActivate/activate on any element.&nbsp; Another thing I saw was that IE is the only browser which fires focus/blur events for any element.&nbsp; Other browsers can support the focus/blur events on any element that has a tab index however.</p> <p>The next version of Calendar needs to support the following activation scenarios depending on whether it is also associated with a button:</p> <ul> <li>No Button</li> <ul> <li>Show Popup when textbox receives focus</li> <li>Show Popup when textbox is clicked </li> <li>Hide Popup when textbox loses focus</li> <li>Hide Popup when textbox receives ESC keypress</li> <li>Hide Popup when a date is selected</li></ul> <li>Button</li> <ul> <li>Show Popup when the button is clicked</li> <li>Hide Popup when the button loses focus</li> <li>Hide Popup when the button receives ESC keypress</li> <li>Hide Popup when a date is selected</li></ul></ul> <p>The issue is that when the textbox or button loses focus the popup should hide <strong>unless </strong>the focus is being directed at the popup itself.&nbsp; The problem is that only IE recognizes a <em>focus</em> event on the popup's DIV tag when the popup is not part of the tab order (and we don't want the popup in the tab order). I was curious the order of DOM events fired in each browser so I wrote a small test page and stepped through for each.&nbsp; The results are as follows:</p> <p>&nbsp;</p> <h4>Table 2 - DOM Event Order by browser</h4> <table cellspacing="0" cellpadding="2" width="764" border="1"> <tbody> <tr> <td valign="top" width="191">IE</td> <td valign="top" width="187">FF</td> <td valign="top" width="187">OP</td> <td valign="top" width="197">SF</td></tr> <tr> <td valign="top" width="190"> <ol> <li><strong>// click on INPUT</strong>  <li>INPUT: mousedown  <li>INPUT: activate  <li>INPUT: focusin  <li>INPUT: focus  <li>INPUT: mouseup  <li>INPUT: click  <li><strong>// click on DIV</strong>  <li>DIV: mousedown  <li>INPUT: deactivate  <li>INPUT: focusout  <li>DIV: activate  <li>DIV: focusin  <li>INPUT: blur  <li>DIV: focus  <li>DIV: mouseup  <li>DIV: click  <li><strong>// click away</strong>  <li>DIV: deactivate  <li>DIV: focusout  <li>DIV: blur</li></ol></td> <td valign="top" width="187"> <ol> <li><strong>// click on INPUT</strong>  <li>INPUT: mousedown  <li>INPUT: focus  <li>INPUT: mouseup  <li>INPUT: click  <li><strong>// click on DIV</strong>  <li>DIV: mousedown  <li>INPUT: blur  <li>DIV: mouseup  <li>DIV: click  <li><strong>// click away</strong></li></ol></td> <td valign="top" width="188"> <ol> <li><strong>// click on INPUT</strong>  <li>INPUT: focus  <li>INPUT: DOMFocusIn  <li>INPUT: mousedown  <li>INPUT: mouseup  <li>INPUT: click  <li><strong>// click on DIV</strong>  <li>INPUT: blur  <li>INPUT: DOMFocusOut  <li>DIV: mousedown  <li>DIV: mouseup  <li>DIV: click  <li><strong>// click away</strong></li></ol></td> <td valign="top" width="197"> <ol> <li><strong>// click on INPUT</strong>  <li>INPUT: mousedown  <li>INPUT: focus  <li>INPUT: DOMFocusIn  <li>INPUT: mouseup  <li>INPUT: click  <li>INPUT: DOMActivate  <li><strong>// click on DIV</strong>  <li>DIV: mousedown  <li>INPUT: blur  <li>INPUT: DOMFocusOut  <li>DIV: mouseup  <li>DIV: click  <li>DIV: DOMActivate  <li><strong>// click away</strong></li></ol></td></tr></tbody></table> <p>&nbsp;</p> <p>Immediately a few things become obvious. First, I obviously cannot rely on focus/blur on the other browsers. IE would allow me to capture <em>focusin </em>on the DIV before the <em>blur</em> fires on the INPUT but that's just IE. Second, on all browsers except Opera the <em>mousedown</em> event of the DIV fires <strong>before</strong> the <em>blur</em> event of the INPUT. There's no clean sequential way to handle the focus transition in all browsers.</p> <p>In the current version of Calendar we're making use of a "threading" class I created for the toolkit called DeferredOperation.&nbsp; DeferredOperation wraps a delegate and executes it asynchronously using setTimout.&nbsp; It has some built-in synchronization semantics and was used to handle the focus changes while the popup DIV was part of the tab order (which again, we don't really want). This introduces a subtle delay between activation requests and is problematic on Safari (we had to wait a full second before processing the deferred operation to let safari to catch up).</p> <p>What I've opted for now is to do the best I can in three out of four of the browsers.&nbsp; I track <em>mousedown/mouseup</em> using a flag and in Internet Explorer, Firefox, and Safari and monitor the flag in the <em>blur</em> event of the textbox. To handle the Opera inconsistency I again use a DeferredOperation to asynchronously handle the <em>blur</em> event which fixes the issue in that browser.</p> <p>The final issue I discovered was that in all browsers, clicking on the popup causes the textbox (or button) to lose focus which again causes problems with the tab order.&nbsp; On the new Calendar I reset the focus to the textbox (or button) on <em>mouseup</em> on the popup.</p> <p>Hopefully these changes should make the next toolkit release so keep an eye out for the next update.</p>]]></content:encoded>
    </item>
  </channel>
</rss>