asyncAction
asyncAction
takes a generator function and automatically wraps all parts of the process in actions. asyncAction
can be used both as decorator or to wrap functions.
- It is important that
asyncAction
should always be used with .a generator function (recognizable asfunction_or_name
syntax). - Each yield statement should return a Promise. The generator function will continue as soon as the promise settles, with the settled value.
- When the generator function finishes, you can return a normal value. The
asyncAction
wrapped function will always produce a promise delivering that value.
When using the MobX DevTools, an asyncAction
will emit action
events with names like:
"fetchUsers - runid: 6 - init"
"fetchUsers - runid: 6 - yield 0"
"fetchUsers - runid: 6 = yield 1"
The runId
represents the generator instance. In other words, if fetchUsers
is invoked multiple times concurrently, the events with the same runid
belong together. The yield
number indicates the progress of the generator. init
indicates spawning (it won't do anything, but you can find the original arguments of the asyncAction
here). yield 0
...yield n
indicates the code block taht is now being executed. yield 0
is before the first yield
, yield 1
after the first one, etc. Note: Yield numbers are not determined lexically, but by the runtime flow.
asyncActions
requires Promise
and generators
to be available on the target environment. Polyfill Promise
if needed. Both TypeScript and Bable can compile generator functions down to ES5.
Parameters
arg1
arg2
Returns
Promise
Examples
import {asyncAction} from "mobx-utils"
let users = []
const fetchUsers = asyncAction("fetchUsers", function* (url) {
const start = Date.now()
const data = yield window.fetch(url)
users = yield data.json()
return start - Date.now()
})
fetchUsers("http://users.com").then(time => {
console.dir("Got users", users, "in ", time, "ms")
})
import {asyncAction} from "mobx-utils"
mobx.useStrict(true) // don't allow state modifications outside actions
class Store {
\@observable githubProjects = []
\@state = "pending" // "pending" / "done" / "error"
\@asyncAction
*fetchProjects() { // <- note the star, this a generator function!
this.githubProjects = []
this.state = "pending"
try {
const projects = yield fetchGithubProjectsSomehow() // yield instead of await
const filteredProjects = somePreprocessing(projects)
// the asynchronous blocks will automatically be wrapped actions
this.state = "done"
this.githubProjects = filteredProjects
} catch (error) {
this.state = "error"
}
}
}