change m.request return value from stream to promise

remove m.prop
add m.Promise
update tests and examples
This commit is contained in:
Leo Horie 2016-11-13 22:44:22 -05:00
parent 8f1a69cfcb
commit bc8cf4ed76
19 changed files with 650 additions and 852 deletions

View file

@ -1,7 +1,8 @@
# Migrating from `v0.2.x` to `v1.x`
`v1.x` is largely API-compatible with `v0.2.x`, but there are a few breaking changes.
`v1.x` is largely API-compatible with `v0.2.x`, but there are some breaking changes.
- [`m.prop` removed](#mprop-removed)
- [`m.component` removed](#mcomponent-removed)
- [`config` function](#config-function)
- [Cancelling redraw from event handlers](#cancelling-redraw-from-event-handlers)
@ -17,13 +18,39 @@
- [`m.request`](#mrequest)
- [`xlink` namespace required](#xlink-namespace-required)
---
## `m.prop` removed
In `v1.x`, `m.prop` is now a more powerful stream micro-library, but it's no longer part of core.
### `v0.2.x`
```javascript
var m = require("mithril")
var num = m.prop(1)
```
### `v1.x`
```javascript
var m = require("mithril")
var prop = require("mithril/stream")
var num = prop(1)
var doubled = num.map(function(n) {return n * 2})
```
---
## `m.component` removed
In `v0.2.x` components could be created using either `m(component)` or `m.component(component)`. `v1.x` only supports `m(component)`.
### `v0.2.x`
```js
```javascript
// These are equivalent
m.component(component);
m(component);
@ -31,10 +58,12 @@ m(component);
### `v1.x`
```js
```javascript
m(component);
```
---
## `config` function
In `v0.2.x` mithril provided a single lifecycle method, `config`. `v1.x` provides much more fine-grained control over the lifecycle of a vnode.
@ -73,6 +102,8 @@ m("div", {
If available the DOM-Element of the vnode can be accessed at `vnode.dom`.
---
## Cancelling redraw from event handlers
`m.mount()` and `m.route()` still automatically redraw after a DOM event handler runs. Cancelling these redraws from within your event handlers is now done by setting the `redraw` property on the passed-in event object to `false`.
@ -97,6 +128,8 @@ m("div", {
})
```
---
## Component `controller` function
In `v1.x` there is no more `controller` property in components, use `oninit` instead.
@ -147,6 +180,8 @@ m.mount(document.body, {
});
```
---
## Component arguments
Arguments to a component in `v1.x` must be an object, simple values like `String`/`Number`/`Boolean` will be treated as text children. Arguments are accessed within the component by reading them from the `vnode.attrs` object.
@ -183,6 +218,8 @@ var component = {
m("div", m(component, { fooga : 1 }));
```
---
## `view()` parameters
In `v0.2.x` view functions are passed a reference to the `controller` instance and (optionally) any options passed to the component. In `v1.x` they are passed **only** the `vnode`, exactly like the `controller` function.
@ -214,6 +251,8 @@ m.mount(document.body, {
});
```
---
## Passing components to `m()`
In `v0.2.x` you could pass components as the second argument of `m()` w/o any wrapping required. To help with consistency in `v1.x` they must always be wrapped with a `m()` invocation.
@ -230,6 +269,8 @@ m("div", component);
m("div", m(component));
```
---
## Passing vnodes to `m.mount()` and `m.route()`
In `v0.2.x`, `m.mount(element, component)` tolerated [vnodes](vnodes.md) as second arguments instead of [components](components.md) (even though it wasn't documented). Likewise, `m.route(element, defaultRoute, routes)` accepted vnodes as values in the `routes` object.
@ -258,24 +299,28 @@ m.route(element, '/', {
})
```
---
## `m.route.mode`
In `v0.2.x` the routing mode could be set by assigning a string of `"pathname"`, `"hash"`, or `"search"` to `m.route.mode`. In `v.1.x` it is replaced by `m.route.prefix(prefix)` where `prefix` can be `#`, `?`, or an empty string (for "pathname" mode). The new API also supports hashbang (`#!`), which is the default, and it supports non-root pathnames and arbitrary mode variations such as querybang (`?!`)
### `v0.2.x`
```js
```javascript
m.route.mode = "pathname";
m.route.mode = "search";
```
### `v1.x`
```js
```javascript
m.route.prefix("");
m.route.prefix("?");
```
---
## `m.route()` and anchor tags
Handling clicks on anchor tags via the mithril router is similar to `v0.2.x` but uses a new lifecycle method and API.
@ -300,6 +345,8 @@ m("a", {
})
```
---
## Reading/writing the current route
In `v0.2.x` all interaction w/ the current route happened via `m.route()`. In `v1.x` this has been broken out into two functions.
@ -324,6 +371,8 @@ m.route.get();
m.route.set("/other/route");
```
---
## Accessing route params
In `v0.2.x` reading route params was all handled through the `m.route.param()` method. In `v1.x` any route params are passed as the `attrs` object on the vnode passed as the first argument to lifecycle methods/`view`.
@ -355,69 +404,80 @@ m.route(document.body, "/booga", {
});
```
---
## m.request
[m.request](request.md) now returns an [m.prop stream](prop.md) instead of a promise. The main difference is you'll have to use `.run` to get similar functionality as a promise's `.then`:
Promises returned by [m.request](request.md) are no longer `m.prop` getter-setters. In addition, `initialValue` is no longer a supported option.
### `v0.2.x`
```js
m.request({ method: 'GET', url: 'https://api.github.com/' })
.then(function (responseBody) {
return m.request({ method: 'GET', url: responseBody.emojis_url });
})
.then(function (emojis) {
console.log("+1 url:", emojis['+1']);
});
```javascript
var data = m.request({
method: "GET",
url: "https://api.github.com/",
initialValue: [],
})
setTimeout(function() {
console.log(data())
}, 1000)
```
### `v1.x`
```js
m.request({ method: 'GET', url: 'https://api.github.com/' })
.run(function (responseBody) {
return m.request({ method: 'GET', url: responseBody.emojis_url });
})
.run(function (emojis) {
console.log("+1 url:", emojis['+1']);
});
```javascript
var data = []
m.request({
method: "GET",
url: "https://api.github.com/",
})
.then(function (responseBody) {
data = responseBody
})
setTimeout(function() {
console.log(data) // note: not a getter-setter
}, 1000)
```
The equivalent of `m.sync` is now `m.prop.merge`:
The equivalent of `m.sync` is now `m.Promise.all`
### `v0.2.x`
```js
```javascript
m.sync([
m.request({ method: 'GET', url: 'https://api.github.com/users/lhorie' }),
m.request({ method: 'GET', url: 'https://api.github.com/users/isiahmeadows' }),
])
.then(function (users) {
console.log("Contributors:", users[0].name, "and", users[1].name);
});
.then(function (users) {
console.log("Contributors:", users[0].name, "and", users[1].name);
})
```
### `v1.x`
```js
m.prop.merge([
```javascript
m.Promise.all([
m.request({ method: 'GET', url: 'https://api.github.com/users/lhorie' }),
m.request({ method: 'GET', url: 'https://api.github.com/users/isiahmeadows' }),
])
.run(function (users) {
console.log("Contributors:", users[0].name, "and", users[1].name);
});
.then(function (users) {
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.
Additionally, if the `extract` option is passed to `m.request` the return value of the provided function will be used directly to resolve its promise, and the `deserialize` callback is ignored.
---
## `xlink` namespace required
In `v0.2.x` when generating SVGs using `m()` the `xlink` namespace would automatically be added on certain attributes. For consistency in `v1.x` if you want to namespace an attribute you must do it yourself.
In `v0.2.x`, the `xlink` namespace was the only supported attribute namespace, and it was supported via special casing behavior. Now namespace parsing is fully supported, and namespaced attributes should explicitly declare their namespace.
### `v0.2.x`
```js
```javascript
m("svg",
// the `href` attribute is namespaced automatically
m("image[href='image.gif']")
@ -426,7 +486,7 @@ m("svg",
### `v1.x`
```js
```javascript
m("svg",
// User-specified namespace on the `href` attribute
m("image[xlink:href='image.gif']")