Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Magic actionAsync (red X is coveralls) #218

Closed
wants to merge 7 commits into from
Closed

Conversation

xaviergonz
Copy link
Contributor

@xaviergonz xaviergonz commented Oct 7, 2019

Basically like #217 except that thanks to a very small Promise tweaking "task" is not needed at all :D

Edit: See comment about chrome below.

actionAsync

Alternative syntax for async actions, similar to flow but more compatible with
Typescript typings. Not to be confused with asyncAction, which is deprecated.

actionAsync can be used either as a decorator or as a function.

It is very important to await for any promises that are created directly inside the async action,
or else an exception will be thrown.

When using the mobx devTools, an asyncAction will emit action events with names like:

  • "fetchUsers - runid 6 - step 0"
  • "fetchUsers - runid 6 - step 1"
  • "fetchUsers - runid 6 - step 2"

The runId represents the action instance. In other words, if fetchUsers is invoked
multiple times concurrently, the events with the same runid belong together.
The step number indicates the code block that is now being executed.

Examples

import {actionAsync} from "mobx-utils"

let users = []

const fetchUsers = actionAsync("fetchUsers", async (url) => {
  const start = Date.now()
  const data = await window.fetch(url)
  users = await data.json()
  return start - Date.now()
})

const time = await fetchUsers("http://users.com")
console.log("Got users", users, "in ", time, "ms")
import {actionAsync} from "mobx-utils"

mobx.configure({ enforceActions: "observed" }) // don't allow state modifications outside actions

class Store {
  @observable githubProjects = []
  @state = "pending" // "pending" / "done" / "error"

  @actionAsync
  async fetchProjects() {
    this.githubProjects = []
    this.state = "pending"
    try {
      const projects = await fetchGithubProjectsSomehow()
      const filteredProjects = somePreprocessing(projects)
      // the asynchronous blocks will automatically be wrapped actions
      this.state = "done"
      this.githubProjects = filteredProjects
    } catch (error) {
       this.state = "error"
    }
  }
}

@coveralls
Copy link

Coverage Status

Coverage decreased (-0.9%) to 93.372% when pulling 38df465 on magic-action-async into 75733b1 on master.

@xaviergonz xaviergonz changed the title Magic actionAsync Magic actionAsync (red X is coveralls) Oct 7, 2019
@xaviergonz
Copy link
Contributor Author

xaviergonz commented Oct 7, 2019

Gah darn, it doesn't seem to work when using native async constructs (at least in Chrome) since those will use the native Promise constructor no matter what. It does work with transpiled code though (and apparently native async when using node).

An option could be to also offer "task", make if compatible with this one and let people know they should use "task" when targeting es6 untranspiled code?

@mweststrate
Copy link
Member

Honestly I'd be very very hesitant to monkey patch a core function like Promise. Even if there is no semantic risk, there is still the risk off blowing up all of the internal javascript engine optimisations by customising these built-ins.

@xaviergonz
Copy link
Contributor Author

Ah shame, I just noticed that overriding .then and friends is supported by native async/await, so I was about to test an idea using those instead

@mweststrate
Copy link
Member

mweststrate commented Oct 7, 2019 via email

@xaviergonz
Copy link
Contributor Author

Found a way to make it work in chrome es6, but that way doesn't work in node es6.
Could make it so it detects the environment and chooses one way or the other, but it is likely not to work very well somewhere else, so closing this pr in favor of the one that uses task. thanks!

@xaviergonz xaviergonz closed this Oct 8, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants