Skip to content

Instantly share code, notes, and snippets.

@anyley
Created September 1, 2016 23:03
Show Gist options
  • Save anyley/a2258482b9b6fdb6bb0d0293471eb341 to your computer and use it in GitHub Desktop.
Save anyley/a2258482b9b6fdb6bb0d0293471eb341 to your computer and use it in GitHub Desktop.
const {
createStore,
combineReducers,
applyMiddleware,
bindActionCreators
} = Redux
const { default: createSagaMiddleware, effects } = ReduxSaga
const { take, put, call, fork, join, cancel, race } = effects
///////////////////////////////////////////////////////////////////
//
// mimics a remote source
//
function fakeSource(url) {
let listener, count = 0
// send a message 5 times each second
const iv = setInterval(() => {
if(count < 5)
listener({ data: `"${url}/${++count}"` })
else {
clearInterval(iv)
listener({data: null})
}
}, 1000)
return {
set onmessage(l) {
listener = l
}
}
}
/////////////////////////////////////////////////////////
//
// our API function
// creates a message iterator: {nextMessage: () -> Promise}
// Promise that will resolve to the next message
function createSource(url) {
const source = fakeSource(url)
let deferred
source.onmessage = event => {
if(deferred) {
deferred.resolve(JSON.parse(event.data))
deferred = null
}
}
return {
nextMessage() {
if(!deferred) {
deferred = {}
deferred.promise =
new Promise(resolve => deferred.resolve = resolve)
}
return deferred.promise
}
}
}
///////////////////////////////////////////////////////////////
//
// Actions
//
const APP_LOADED = 'APP_LOADED'
const appLoaded = () =>({type: APP_LOADED})
const receive = (message) => ({type: 'RECEIVE', message})
///////////////////////////////////////////////////////////////
//
// Reducers
//
function messageList(state = [], action) {
if(action.message)
return [...state, action.message]
return state
}
const rootReducer = combineReducers({
messageList
})
///////////////////////////////////////////////////////////////
//
// Sagas
//
function* watchMessages(msgSource) {
console.log('begin receive messages')
let msg = yield call(msgSource.nextMessage)
while(msg) {
yield put(receive(msg))
msg = yield call(msgSource.nextMessage)
}
console.log('done receive messages')
}
function* getMessagesOnLoad() {
yield take('APP_LOADED')
const msgSource = yield call(createSource, '/myurl')
yield fork(watchMessages, msgSource)
}
const saga = getMessagesOnLoad
///////////////////////////////////////////////////////////////
//
// Create the store. Log states into the console
//
const sagaMiddleware = createSagaMiddleware()
const store = createStore(
rootReducer,
applyMiddleware(sagaMiddleware)
)
sagaMiddleware.run(saga)
let lastState
store.subscribe(() => {
const state = store.getState()
if(state !== lastState) {
lastState = state
console.log(lastState.messageList)
}
})
/* test */
store.dispatch(appLoaded())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment