make xhr.abort reject promise chain

This commit is contained in:
Leo Horie 2014-04-29 22:19:07 -04:00
parent c1f6705a59
commit 38dba03f6d
11 changed files with 69 additions and 13 deletions

View file

@ -62,6 +62,12 @@
</div>
<div class="col(9,9,12)">
<h2 id="change-log">Change Log</h2>
<p><a href="/mithril/archive/v0.1.11">v0.1.11</a> - maintenance</p>
<h3 id="news-">News:</h3>
<ul>
<li>Added <code>m.route()</code> overload to allow reading of current route <a href="https://github.com/lhorie/mithril.js/issues/61">#61</a></li>
</ul>
<hr>
<p><a href="/mithril/archive/v0.1.10">v0.1.10</a> - maintenance</p>
<h3 id="news-">News:</h3>
<ul>

View file

@ -163,7 +163,6 @@ dashboard.controller = function() {
};
dashboard.view = function(ctrl) {
//assuming there&#39;s an element w/ id = &quot;example&quot; somewhere on the page
return m(&quot;#example&quot;, [
new autocompleter.view(ctrl.autocompleter, {onchange: m.withAttr(&quot;value&quot;, console.log)}),
]);

View file

@ -214,7 +214,7 @@ m.render(todo.view(ctrl)); // input now says &quot;Write code&quot;</code></pre>
<hr>
<p>In addition to bi-directional data binding, we can also bind parameterized functions to events:</p>
<pre><code class="lang-javascript">m(&quot;button&quot;, {onclick: ctrl.add.bind(ctrl, ctrl.description)}, &quot;Add&quot;)</code></pre>
<p>In the code above, we are simply using the native Javascript <code>Function::bind</code> method. This creates a new function with the parameter already set. In functional programming, this is called <a href="http://en.wikipedia.org/wiki/Currying"><em>currying</em></a>.</p>
<p>In the code above, we are simply using the native Javascript <code>Function::bind</code> method. This creates a new function with the parameter already set. In functional programming, this is called <a href="http://en.wikipedia.org/wiki/Partial_application"><em>partial application</em></a>.</p>
<p>The <code>ctrl.add.bind(ctrl, ctrl.description)</code> expression above returns a function that is equivalent to this code:</p>
<pre><code class="lang-javascript">onclick: function(e) {
ctrl.add(ctrl.description)
@ -262,7 +262,7 @@ m(&quot;table&quot;, [
<ul>
<li>The template is rendered as a child of the implicit <code>&lt;html&gt;</code> element of the document</li>
<li>The text input saves its value to the <code>ctrl.description</code> getter-setter we defined earlier</li>
<li><p>The button calls the <code>ctrl.add</code> method when clicked. The <code>.bind(ctrl, ctrl.description)</code> idiom is a <a href="http://en.wikipedia.org/wiki/Currying">functional curry</a>.</p>
<li><p>The button calls the <code>ctrl.add</code> method when clicked. The <code>.bind(ctrl, ctrl.description)</code> idiom is a <a href="http://en.wikipedia.org/wiki/Partial_application">partial application</a>.</p>
<p>In this example, it&#39;s only used to maintain the scope binding for the <code>this</code> parameter in the controller method, but typically it&#39;s also used to bind parameters to the function without the need to declare a wrapper anonymous function.</p>
</li>
<li>The table lists all the existing to-dos, if any.</li>
@ -409,7 +409,7 @@ this.description = function(value) {
<p>Another feature - the optional <code>m()</code> utility - allows writing terse templates in a declarative style using CSS shorthands, similar to popular HTML preprocessors from server-side MVC frameworks.</p>
<p>And because Mithril views are javascript, the developer has full freedom to abstract common patterns - from bidirectional binding helpers to full blown components - using standard javascript refactoring techniques.</p>
<p>Mithril templates are also more collision-proof than other component systems since there&#39;s no way to pollute the HTML tag namespace by defining ad-hoc tag names.</p>
<p>A more intellectually interesting aspect of the framework is that event handling is encouraged to be done via functional composition (i.e. by using tools like <a href="mithril.withAttr.html"><code>m.withAttr</code></a>, <a href="mithril.prop.html"><code>m.prop</code></a> and the native <code>.bind()</code> method for currying).</p>
<p>A more intellectually interesting aspect of the framework is that event handling is encouraged to be done via functional composition (i.e. by using tools like <a href="mithril.withAttr.html"><code>m.withAttr</code></a>, <a href="mithril.prop.html"><code>m.prop</code></a> and the native <code>.bind()</code> method for partial application).</p>
<p>If you&#39;ve been interested in learning or using Functional Programming in the real world, Mithril provides very pragmatic opportunities to get into it.</p>
<hr>
<h2 id="learn-more">Learn More</h2>

View file

@ -398,6 +398,9 @@ Mithril = m = new function app(window) {
xhr.open(options.method, options.url, true, options.user, options.password)
xhr.onload = typeof options.onload == "function" ? options.onload : function() {}
xhr.onerror = typeof options.onerror == "function" ? options.onerror : function() {}
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 0) xhr.onerror({type: "error", target: xhr})
}
if (typeof options.config == "function") options.config(xhr, options)
xhr.send(options.data)
return xhr
@ -1012,6 +1015,24 @@ function testMithril(mock) {
var paramValueAfter = m.route.param("a1")
return mock.location.search == "?/" && paramValueBefore === "foo" && paramValueAfter === undefined
})
test(function() {
//https://github.com/lhorie/mithril.js/issues/61
mock.performance.$elapse(50)
mock.location.search = "?"
var module = {controller: function() {}, view: function() {return m.route.param("a1")}}
var root = mock.document.createElement("div")
m.route.mode = "search"
m.route(root, "/test7/foo", {
"/": module,
"/test7/:a1": module
})
var routeValueBefore = m.route()
m.route("/")
var routeValueAfter = m.route()
return routeValueBefore === "/test7/foo" && routeValueAfter === "/"
})
//m.prop
test(function() {

View file

@ -398,6 +398,9 @@ Mithril = m = new function app(window) {
xhr.open(options.method, options.url, true, options.user, options.password)
xhr.onload = typeof options.onload == "function" ? options.onload : function() {}
xhr.onerror = typeof options.onerror == "function" ? options.onerror : function() {}
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 0) xhr.onerror({type: "error", target: xhr})
}
if (typeof options.config == "function") options.config(xhr, options)
xhr.send(options.data)
return xhr

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

View file

@ -233,6 +233,15 @@ m.request({method: &quot;POST&quot;, url: &quot;/foo&quot;, extract: extract});<
m.request({method: &quot;POST&quot;, url: &quot;/foo&quot;, config: xhrConfig});</code></pre>
<hr>
<h3 id="aborting-a-request">Aborting a request</h3>
<p>The <code>config</code> option can also be used to retrieve the <code>XMLHttpRequest</code> instance for aborting the request. This idiom can also be used to attach <code>onprogress</code> event handlers.</p>
<pre><code class="lang-javascript">var transport = m.prop();
m.request({method: &quot;POST&quot;, url: &quot;/foo&quot;, config: transport});
//the `transport` getter-setter contains an instance of XMLHttpRequest
transport().abort();</code></pre>
<hr>
<h3 id="signature">Signature</h3>
<p><a href="how-to-read-signatures.html">How to read signatures</a></p>
<pre><code class="lang-clike">Promise request(XHROptions options)
@ -277,7 +286,7 @@ where:
<p>Data to be sent. It&#39;s automatically placed in the appropriate section of the request with the appropriate serialization based on <code>method</code></p>
</li>
<li><p><strong>any unwrapSuccess(any data)</strong> (optional)</p>
<p>A preprocessor function to extract the data from a success response in case the response contains metadata wrapping the data.</p>
<p>A preprocessor function to unwrap the data from a success response in case the response contains metadata wrapping the data.</p>
<p>The default value (if this parameter is falsy) is the identity function <code>function(value) {return value}</code></p>
<p>For example, if the response is <code>{data: [{name: &quot;John&quot;}, {name: &quot;Mary&quot;}]}</code> and the unwrap function is <code>function(response) {return response.data}</code>, then the response will be considered to be <code>[{name: &quot;John&quot;}, {name: &quot;Mary&quot;}]</code> when processing the <code>type</code> parameter</p>
<ul>
@ -290,7 +299,7 @@ where:
</ul>
</li>
<li><p><strong>any unwrapError(any data)</strong> (optional)</p>
<p>A preprocessor function to extract the data from an error response in case the response contains metadata wrapping the data.</p>
<p>A preprocessor function to unwrap the data from an error response in case the response contains metadata wrapping the data.</p>
<p>The default value (if this parameter is falsy) is the identity function <code>function(value) {return value}</code></p>
<ul>
<li><p><strong>Object<any> | Array<any> data</strong></p>
@ -325,7 +334,7 @@ where:
</li>
<li><p><strong>any extract(XMLHttpRequest xhr, XHROptions options)</strong> (optional)</p>
<p>Method to use to extract the data from the raw XMLHttpRequest. This is useful when the relevant data is either in a response header or the status field.</p>
<p>If this parameter is falsy, the default value is <code>function(xhr, options) {return xhr.responseText}</code>.</p>
<p>If this parameter is falsy, the default value is a function that returns <code>xhr.responseText</code>.</p>
</li>
<li><p><strong>void type(Object<any> data)</strong> (optional)</p>
<p>The response object (or the child items if this object is an Array) will be passed as a parameter to the class constructor defined by <code>type</code></p>

View file

@ -259,6 +259,21 @@ m.request({method: "POST", url: "/foo", config: xhrConfig});
---
### Aborting a request
The `config` option can also be used to retrieve the `XMLHttpRequest` instance for aborting the request. This idiom can also be used to attach `onprogress` event handlers.
```javascript
var transport = m.prop();
m.request({method: "POST", url: "/foo", config: transport});
//the `transport` getter-setter contains an instance of XMLHttpRequest
transport().abort();
```
---
### Signature
[How to read signatures](how-to-read-signatures.md)
@ -315,7 +330,7 @@ where:
- **any unwrapSuccess(any data)** (optional)
A preprocessor function to extract the data from a success response in case the response contains metadata wrapping the data.
A preprocessor function to unwrap the data from a success response in case the response contains metadata wrapping the data.
The default value (if this parameter is falsy) is the identity function `function(value) {return value}`
@ -331,7 +346,7 @@ where:
- **any unwrapError(any data)** (optional)
A preprocessor function to extract the data from an error response in case the response contains metadata wrapping the data.
A preprocessor function to unwrap the data from an error response in case the response contains metadata wrapping the data.
The default value (if this parameter is falsy) is the identity function `function(value) {return value}`
@ -371,7 +386,7 @@ where:
Method to use to extract the data from the raw XMLHttpRequest. This is useful when the relevant data is either in a response header or the status field.
If this parameter is falsy, the default value is `function(xhr, options) {return xhr.responseText}`.
If this parameter is falsy, the default value is a function that returns `xhr.responseText`.
- **void type(Object<any> data)** (optional)

View file

@ -398,6 +398,9 @@ Mithril = m = new function app(window) {
xhr.open(options.method, options.url, true, options.user, options.password)
xhr.onload = typeof options.onload == "function" ? options.onload : function() {}
xhr.onerror = typeof options.onerror == "function" ? options.onerror : function() {}
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 0) xhr.onerror({type: "error", target: xhr})
}
if (typeof options.config == "function") options.config(xhr, options)
xhr.send(options.data)
return xhr