Rewrite: ignore m.request deserialize option if extract is passed

This commit is contained in:
Patrik Johnson 2016-08-04 19:19:12 +03:00
parent 0d1c1a3f16
commit 88e7cf5454
4 changed files with 43 additions and 4 deletions

View file

@ -32,7 +32,7 @@ Argument | Type | Required | Descript
`options.type` | `any = Function(any)` | No | A constructor to be applied to each object in the response. Defaults to the [identity function](https://en.wikipedia.org/wiki/Identity_function).
`options.serialize` | `string = Function(any)` | No | A serialization method to be applied to `data`. Defaults to `JSON.stringify`, or if `options.data` is an instance of [`FormData`](https://developer.mozilla.org/en/docs/Web/API/FormData), defaults to the [identity function](https://en.wikipedia.org/wiki/Identity_function) (i.e. `function(value) {return value}`).
`options.deserialize` | `any = Function(string)` | No | A deserialization method to be applied to the response. Defaults to a small wrapper around `JSON.parse` that returns `null` for empty responses.
`options.extract` | `string = Function(xhr, options)` | No | A hook to specify how the XMLHttpRequest response should be read. Useful for reading response headers and cookies. Defaults to a function that returns `xhr.responseText`
`options.extract` | `string = Function(xhr, options)` | No | A hook to specify how the XMLHttpRequest response should be read. Useful for reading response headers and cookies. Defaults to a function that returns `xhr.responseText`. If defined, `options.deserialize` is ignored.
`options.initialValue` | `any` | No | A value to populate the returned stream before the request completes
`options.useBody` | `Boolean` | No | Force the use of the HTTP body section for `data` in `GET` requests when set to `true`, or the use of querystring for other HTTP methods when set to `false`. Defaults to `false` for `GET` requests and `true` for other methods.
**returns** | `Stream` | | A stream that resolves to the response data, after it has been piped through the `extract`, `deserialize` and `type` methods
@ -378,6 +378,26 @@ Ignoring the fact that the parseCSV function above doesn't handle a lot of cases
---
### Retrieving response details
By default Mithril attempts to parse a response as JSON and returns `xhr.responseText`. It may be useful to inspect a server response in more detail, this can be accomplished by passing a custom `options.extract` function:
```javascript
m.request({
method: "GET",
url: "/api/v1/users",
extract: function(xhr) {return {status: xhr.status, body: xhr.responseText}}
})
.run(function(response) {
console.log(response.status, response.body)
})
```
The parameter to `options.extract` is the XMLHttpRequest object once its operation is completed, but before it has been passed to the resulting [stream](prop.md), so the stream may still end up in an errored state if processing throws an exception.
---
### Why JSON instead of HTML
Many server-side frameworks provide a view engine that interpolates database data into a template before serving HTML (on page load or via AJAX) and then employ jQuery to handle user interactions.

View file

@ -330,3 +330,5 @@ m.prop.merge([
console.log("Contributors:", users[0].name, "and", users[1].name);
});
```
Additionally, if the `extract` option is passed to `m.request` the return value of the provided function will be passed to the [m.prop stream](prop.md) directly, and any `deserialize` callback is ignored.

View file

@ -38,7 +38,7 @@ module.exports = function($window) {
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
try {
var response = args.deserialize(args.extract(xhr, args))
var response = (args.extract !== extract) ? args.extract(xhr, args) : args.deserialize(args.extract(xhr, args))
if (xhr.status >= 200 && xhr.status < 300) {
stream(cast(args.type, response))
}

View file

@ -210,7 +210,7 @@ o.spec("xhr", function() {
}
})
xhr({method: "GET", url: "/item", extract: extract}).map(function(data) {
o(data).deepEquals({test: 123})
o(data).equals("{\"test\":123}")
}).map(done)
})
o("extract parameter works in POST", function(done) {
@ -224,7 +224,24 @@ o.spec("xhr", function() {
}
})
xhr({method: "POST", url: "/item", extract: extract}).map(function(data) {
o(data).deepEquals({test: 123})
o(data).equals("{\"test\":123}")
}).map(done)
})
o("ignores deserialize if extract is defined", function(done) {
var extract = function(data) {
return data.status
}
var deserialize = o.spy()
mock.$defineRoutes({
"GET /item": function(request) {
return {status: 200, responseText: ""}
}
})
xhr({method: "GET", url: "/item", extract: extract, deserialize: deserialize}).map(function(data) {
o(data).equals(200)
}).map(function() {
o(deserialize.callCount).equals(0)
}).map(done)
})
o("config parameter works", function(done) {