Skip to content

Instantly share code, notes, and snippets.

@daniel12fsp
Last active February 8, 2020 14:24
Show Gist options
  • Save daniel12fsp/6cdecbd13f51cfe3da168bc479386365 to your computer and use it in GitHub Desktop.
Save daniel12fsp/6cdecbd13f51cfe3da168bc479386365 to your computer and use it in GitHub Desktop.
Implement a simple generator capable to support redux-saga syntaxe
const symbol = Symbol('IS_GEN')
const makeGen = (gen) => gen[symbol] = true
const isGen = (gen) => Boolean(gen[symbol])
function takeLatest(action, fnGenerator) {
makeGen(fnGenerator)
return {
effect: "takeLatest",
action,
fnGenerator
}
}
function take(action, ) {
return {
effect: "take",
action,
}
}
function put(action) {
return {
effect: "put",
action,
}
}
function fork(fnGenerator) {
makeGen(fnGenerator)
return {
effect: "fork",
fnGenerator
}
}
function cancel(action, fnGenerator) {
return {
effect: "cancel",
action,
fnGenerator
}
}
function* actionA(payload) {
console.log("=> actionA")
yield put("ACTION-B")
}
function* actionB(payload) {
console.log("=> actionB")
const taskId = yield fork(actionC)
console.log("=> actionB - fim")
yield take("ACTION-CANCEL")
console.log("cancelar")
}
function* actionC(payload) {
console.log("=> actionC")
}
function* main() {
// console.log("main")
yield takeLatest("ACTION-A", actionA)
yield takeLatest("ACTION-B", actionB)
// yield takeLatest("ACTION-C", actionC)
}
function runGen({ iter, takers, run, gens }) {
let result = iter.next();
let yield$;
while (!result.done) {
const yieldedValue = result.value;
if (iter.cancelRequest) {
return;
}
switch (yieldedValue.effect) {
case "takeLatest":
takers[yieldedValue.action] = yieldedValue
break;
case "put":
const action = yieldedValue.action
run(action)
break;
case "fork":
const iter1 = yieldedValue.fnGenerator()
yield$ = runGen({ iter: iter1, takers, run })
break;
case "take":
const gen = {
fnGenerator: () => iter,
yieldedValue
};
makeGen(gen.fnGenerator)
takers[yieldedValue.action] = gen
return result;
break;
default:
break;
}
result = iter.next(yield$);
}
}
function createRun(saga) {
const takers = {};
const gens = {};
return function run(action) {
const iter = saga();
if (!Object.keys(takers).length) {
runGen({ iter, takers, gens });
}
const taker = takers[action];
if (taker) {
const fnCall = taker.fnGenerator
if (isGen(fnCall)) {
const value = fnCall()
runGen({ iter: value, takers, run, gens })
}
if (taker.yieldedValue) {
delete takers[taker.yieldedValue.action]
}
}
console.log(takers)
return iter;
}
}
const run = createRun(main)
run("ACTION-A")
console.log("ACTION-CANCEL")
run("ACTION-CANCEL")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment