Created
May 5, 2019 22:48
-
-
Save CreatCodeBuild/3d46fc895ea5debbc7b3ddf92a52890d to your computer and use it in GitHub Desktop.
Why "Generator is already running"? I need help!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const EventEmitter = require('events'); | |
class MyEmitter extends EventEmitter { } | |
let e = new MyEmitter() | |
const DriveMainLoop = Symbol("DriveMainLoop"); | |
// eventBus must be the kernel/task this sleeper belongs to | |
function Sleeper(eventBus, doneToken) { | |
return { | |
Sleep: function (time) { | |
setTimeout(function () { | |
eventBus.emit(doneToken) | |
}, time); | |
}, | |
} | |
} | |
function Task(e, gf) { | |
const advanceToken = Symbol("advanceToken"); | |
const doneToken = Symbol("doneToken"); | |
let ret; | |
let done; | |
let task = { | |
join: function () { | |
if (done) { | |
done = false; | |
e.emit(doneToken, ret) // ???? TypeError: Generator is already running | |
return | |
} | |
e.on("task return", (data)=> { | |
done = false; | |
e.emit(DriveMainLoop, data) | |
}) | |
}, // should return a future with a resolve as a callback | |
Sleep: Sleeper(e, advanceToken).Sleep, | |
advanceToken: advanceToken, | |
doneToken: doneToken, | |
setResult: function(result) { | |
e.emit("task return", result) | |
done = true | |
ret = result | |
} | |
} | |
let g = gf(task) | |
task.next = function(data) { | |
return g.next(data) | |
} | |
return task | |
} | |
function Kernel() { | |
let mainTask; | |
return { | |
Go: function (gf) { | |
let t = Task(e, gf); | |
e.on(t.doneToken, (data)=>{ | |
mainTask.next(data); | |
}); | |
e.on(t.advanceToken, (data)=> { | |
try { | |
let step = t.next(data); | |
if (step.done) { | |
t.setResult(step.value) | |
} | |
} catch (e) { | |
console.log("task err", e) | |
} | |
}); | |
e.emit(t.advanceToken) | |
return t | |
}, | |
Run: function (gf) { | |
mainTask = gf(); | |
let g = mainTask; | |
e.on(DriveMainLoop, (data) => { | |
try { | |
let mainLoopResult = g.next(data); | |
} catch (e) { | |
console.log("main err", e) | |
} | |
}); | |
e.emit(DriveMainLoop); | |
}, | |
Sleep: Sleeper(e, DriveMainLoop).Sleep, | |
} | |
} | |
let kernel = Kernel(); | |
kernel.Run(function* () { | |
let task = kernel.Go(function* (t) { | |
for (let i = 0; i < 2; i++) { | |
yield t.Sleep(200) | |
console.log("child job slept", i) | |
} | |
return "child job done!" | |
}) | |
for (let i = 0; i < 5; i++) { | |
yield kernel.Sleep(200) | |
console.log("slept", i) | |
} | |
console.log("after for loop") | |
console.log("main loop", yield task.join()) // print child job done | |
}); | |
console.log("blocked?"); // kernel Run does not block. |
Just change line 92 in your code to name your Generator like below, I find that you call the main generator recursively. That is the problem.
If you call Generator.next
in generator function itself, will throw TypeError: Generator is already running
-- kernel.Run(function* () {
++ kernel.Run(function * runGenerator() {
that is my log
blocked?
child job slept 0
slept 0
child job slept 1
slept 1
slept 2
slept 3
slept 4
after for loop
main err TypeError: Generator is already running
at runGenerator.next (<anonymous>) // <- where the recursive call happen
at MyEmitter.Go.e.on (/Users/cheeqi/DEV/temp/js/csp.js:59:26)
at emitOne (events.js:115:13)
at MyEmitter.emit (events.js:210:7)
at Object.join (/Users/cheeqi/DEV/temp/js/csp.js:28:19)
at runGenerator (/Users/cheeqi/DEV/temp/js/csp.js:105:41)
at runGenerator.next (<anonymous>)
at MyEmitter.Run.e.on (/Users/cheeqi/DEV/temp/js/csp.js:80:44)
at emitNone (events.js:105:13)
at MyEmitter.emit (events.js:207:7)
e.on(t.doneToken, (data)=>{
setImmediate(()=>{mainTask.next(data)})
});
L58
- e.on(t.doneToken, (data)=>{
- mainTask.next(data);
- });
+ e.on(task.doneToken, data => setTimeout(() => mainTask.next(data)))
Ref:
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I was trying to write this small library for teaching purpose. But I encountered a bug.
The implementation isn't the best JS you can see but I believe the idea is clear.