Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
A simplified implementation of redux-saga middleware
<!doctype html>
<html lang="en">
<body>
<script>
const sagaMiddleware = store => gen => {
var resolve, reject
var done = new Promise((res, rej) => {
resolve = res
reject = rej
})
Promise.resolve().then(nextStep)
return {done}
function nextStep(lastResult, isError) {
try {
const {value, done} = !isError ? gen.next(lastResult) : gen.throw(lastResult)
if(done) {
resolve(value)
}
else {
execEffect(value).then(
nextStep,
error => nextStep(error, true)
)
}
}
catch(err) {
reject(err)
}
}
function execEffect(eff) {
if(eff.type === 'CALL') {
return eff.fn(...eff.args)
}
if(eff.type === 'PUT') {
return Promise.resolve(store.dispatch(eff.action))
}
if(eff.type === 'SELECT') {
return Promise.resolve(eff.selector ? eff.selector(store.getState) : store.getState())
}
return Promise.resolve(eff)
}
}
const state = []
const runSaga = sagaMiddleware({
getState() {
return state
},
dispatch(action) {
state.push(action)
console.log('dispatching', action)
}
})
const call = (fn, ...args) => ({type: 'CALL', fn, args})
const put = (action) => ({type: 'PUT', action})
const select = (selector) => ({type: 'SELECT', selector})
function delay(ms) {
return new Promise(res => {
setTimeout(res, ms)
})
}
function* saga(pauseDelay) {
yield put('Action 1')
console.log('pausing for', pauseDelay)
yield call(delay, pauseDelay)
console.log('getting state')
const state = yield select()
return state
}
runSaga(saga(1000)).done.then(
result => console.log('saga terminated', result),
error => console.error('saga aborted with', error)
)
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.