diff --git a/docs/change-log.md b/docs/change-log.md index bdbd2866..eaeeac63 100644 --- a/docs/change-log.md +++ b/docs/change-log.md @@ -14,6 +14,7 @@ - Throwing exceptions within `m.request` now follow the same resolution procedure as `m.deferred` [#86](https://github.com/lhorie/mithril.js/issues/85) - Promises now always update their `m.prop` on success (and leave the m.prop alone on error) - Nested arrays no longer cause double removal of elements [#87](https://github.com/lhorie/mithril.js/issues/87) +- HTTP error codes now correctly reject promises --- diff --git a/mithril.js b/mithril.js index bc4bc222..11a8c69e 100644 --- a/mithril.js +++ b/mithril.js @@ -162,7 +162,10 @@ Mithril = m = new function app(window) { return cachedAttrs } function clear(nodes) { - for (var i = nodes.length - 1; i > -1; i--) nodes[i].parentNode.removeChild(nodes[i]) + if (nodes.length > 0) { + var parent = nodes[i].parentNode + for (var i = nodes.length - 1; i > -1; i--) parent.removeChild(nodes[i]) + } nodes.length = 0 } function injectHTML(parentElement, index, data) { @@ -450,11 +453,10 @@ Mithril = m = new function app(window) { function ajax(options) { var xhr = window.XDomainRequest ? new window.XDomainRequest : new window.XMLHttpRequest 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 (xhr.readyState === 4) { + if (xhr.status >= 200 && xhr.status < 300) options.onload({type: "load", target: xhr}) + else options.onerror({type: "error", target: xhr}) } } if (typeof options.config == "function") options.config(xhr, options) diff --git a/tests/mithril-tests.js b/tests/mithril-tests.js index 37da9b82..69e5040c 100644 --- a/tests/mithril-tests.js +++ b/tests/mithril-tests.js @@ -678,40 +678,34 @@ function testMithril(mock) { //m.request test(function() { var prop = m.request({method: "GET", url: "test"}) - var e = mock.XMLHttpRequest.$events.pop() - e.target.onload(e) + mock.XMLHttpRequest.$instances.pop().onreadystatechange() return prop().method === "GET" && prop().url === "test" }) test(function() { var prop = m.request({method: "GET", url: "test"}).then(function(value) {return "foo"}) - var e = mock.XMLHttpRequest.$events.pop() - e.target.onload(e) + mock.XMLHttpRequest.$instances.pop().onreadystatechange() return prop() === "foo" }) test(function() { var prop = m.request({method: "POST", url: "http://domain.com:80", data: {}}).then(function(value) {return value}) - var e = mock.XMLHttpRequest.$events.pop() - e.target.onload(e) + mock.XMLHttpRequest.$instances.pop().onreadystatechange() return prop().url === "http://domain.com:80" }) test(function() { var prop = m.request({method: "POST", url: "http://domain.com:80/:test1", data: {test1: "foo"}}).then(function(value) {return value}) - var e = mock.XMLHttpRequest.$events.pop() - e.target.onload(e) + mock.XMLHttpRequest.$instances.pop().onreadystatechange() return prop().url === "http://domain.com:80/foo" }) test(function() { var error = m.prop("no error") var prop = m.request({method: "GET", url: "test", deserialize: function() {throw new Error("error occurred")}}).then(null, error) - var e = mock.XMLHttpRequest.$events.pop() - e.target.onload(e) + mock.XMLHttpRequest.$instances.pop().onreadystatechange() return prop() === undefined && error().message === "error occurred" }) test(function() { var error = m.prop("no error"), exception var prop = m.request({method: "GET", url: "test", deserialize: function() {throw new SyntaxError("error occurred")}}).then(null, error) - var event = mock.XMLHttpRequest.$events.pop() - try {event.target.onload(event)} + try {mock.XMLHttpRequest.$instances.pop().onreadystatechange()} catch (e) {exception = e} m.endComputation() return prop() === undefined && error() === "no error" && exception.message == "error occurred" diff --git a/tests/mock.js b/tests/mock.js index c48be899..88534df0 100644 --- a/tests/mock.js +++ b/tests/mock.js @@ -88,10 +88,12 @@ mock.window = new function() { } this.send = function() { this.responseText = JSON.stringify(this) - request.$events.push({type: "load", target: this}) + this.readyState = 4 + this.status = 200 + request.$instances.push(this) } } - request.$events = [] + request.$instances = [] return request } window.location = {search: "", pathname: "", hash: ""},