Skip to content

Commit

Permalink
An opinionated way of doing async with alt
Browse files Browse the repository at this point in the history
  • Loading branch information
goatslacker committed May 6, 2015
1 parent 75667a7 commit 33ca0c1
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 0 deletions.
33 changes: 33 additions & 0 deletions src/alt/utils/StoreMixins.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,39 @@ export const StoreMixinEssentials = {
this.dispatcher.waitFor(tokens)
},

exportAsync(asyncMethods) {
const toExport = Object.keys(asyncMethods).reduce((publicMethods, methodName) => {
const asyncSpec = asyncMethods[methodName]

const validHandlers = ['success', 'error', 'loading']
validHandlers.forEach((handler) => {
if (asyncSpec[handler] && !asyncSpec[handler][ACTION_KEY]) {
throw new Error(`${handler} handler must be an action function`)
}
})

publicMethods[methodName] = (...args) => {
const state = this.getInstance().getState()
const value = asyncSpec.cache(state, ...args)

// if we don't have it in cache then fetch it
if (!value) {
if (asyncSpec.loading) asyncSpec.loading()
asyncSpec.fetch(state, ...args)
.then(asyncSpec.success)
.catch(asyncSpec.error)
} else {
// otherwise emit the change now
this.emitChange()
}
}

return publicMethods
}, {})

this.exportPublicMethods(toExport)
},

exportPublicMethods(methods) {
Object.keys(methods).forEach((methodName) => {
if (typeof methods[methodName] !== 'function') {
Expand Down
4 changes: 4 additions & 0 deletions src/alt/utils/StoreUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,10 @@ export function createStoreFromClass(alt, StoreModel, key, ...argsForClass) {

const store = new Store(...argsForClass)

if (config.datasource) {
StoreMixinEssentials.exportAsync.call(Store.prototype, config.datasource)
}

storeInstance = assign(
new AltStore(
alt,
Expand Down
8 changes: 8 additions & 0 deletions src/utils/decorators.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,11 @@ export function createStore(alt, ...args) {
return alt.createStore(Store, undefined, ...args)
}
}

export function datasource(source) {
return function (Store) {
Store.config = Store.config || {}
Store.config.datasource = source
return Store
}
}
67 changes: 67 additions & 0 deletions stargazer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import Alt from './'
import { createStore, datasource } from './utils/decorators'
import axios from 'axios'

const alt = new Alt()

const StargazerActions = alt.generateActions(
'fetchingUsers',
'usersReceived',
'failed'
)

const StargazerSource = {
fetchUsers: {
fetch(state) {
const url = `https://api.github.com/repos/${state.user}/${state.repo}/stargazers`
return axios({ url }).then(response => response.data)
},

cache(state) {
return state.users.length ? state.users : null
},

loading: StargazerActions.fetchingUsers,

success: StargazerActions.usersReceived,

error: StargazerActions.failed
}
}

@createStore(alt)
@datasource(StargazerSource)
class StargazerStore {
constructor() {
this.user = 'goatslacker'
this.repo = 'alt'
this.users = []
this.errorMessage = null
this.isLoading = false

this.bindListeners({
loading: StargazerActions.fetchingUsers,
receivedUsers: StargazerActions.usersReceived,
failed: StargazerActions.failed
})
}

loading() {
console.log('STORE: starting to load users')
this.isLoading = true
}

failed(e) {
console.log('STORE: Uh oh')
this.errorMessage = e.statusText || String(e)
}

receivedUsers(users) {
console.log('STORE: got users')
this.users = users
this.errorMessage = null
}
}

StargazerStore.listen((state) => console.log('CHANGED', state.users.length))
StargazerStore.fetchUsers()

0 comments on commit 33ca0c1

Please sign in to comment.