-
-
Save creationix/5544019 to your computer and use it in GitHub Desktop.
tim@touchsmart:~/Code$ nvm use v0.11.2-generators | |
Now using node v0.11.2-generators | |
tim@touchsmart:~/Code$ node --harmony testgen.js | |
<Buffer 76 61 72 20 66 73 20 3d 20 72 65 71 75 69 72 65 28 27 66 73 27 29 3b 0a 66 75 6e 63 74 69 6f 6e 20 72 65 61 64 46 69 6c 65 28 70 61 74 68 2c 20 65 6e 63 ...> | |
Sleeping for 2000ms... | |
Done |
var fs = require('fs'); | |
function readFile(path, encoding) { | |
return function (callback) { | |
fs.readFile(path, encoding, callback); | |
}; | |
} | |
function sleep(ms) { | |
return function (callback) { | |
setTimeout(callback, ms); | |
}; | |
} | |
function run(makeGenerator) { | |
return function () { | |
var generator = makeGenerator.apply(this, arguments); | |
var continuable, sync, value; | |
next(); | |
function next() { | |
while (!(continuable = generator.send(value)).done) { | |
continuable = continuable.value; | |
sync = undefined; | |
continuable(callback); | |
if (sync === undefined) { | |
sync = false; | |
break; | |
} | |
} | |
} | |
function callback(err, val) { | |
if (err) return generator.throw(err); | |
value = val; | |
if (sync === undefined) { | |
sync = true; | |
} | |
else { | |
next(); | |
} | |
} | |
} | |
} | |
run(function* () { | |
console.log(yield readFile(__filename)); | |
console.log("Sleeping for 2000ms..."); | |
yield sleep(2000); | |
console.log("Done"); | |
})(); |
I don't really think this is clean. It looks too implicit, also I believe that sync variable is not the most elegant way to solve the problem. Moreover, the problem is that function run take too much responsibility working as a proxy between real async functions and code inside the generator (and you need to wrap all functions in another function). In my opinion, the way jmar777/suspend solves this problem providing the resume
function is more explicit and clean.
@Termina1 yes, yes, and yes. just about what i thought when perusing the code.
@Termina1 what's a better way other than the sync
variable to detect if the callback was called before or after the continuable returned? I'm open to cleaner code, I don't like all this boilerplate.
Also reading through suspend's code, it appears he is vulnerable to stack overflows if the callbacks are called before the parent function returns. If I didn't have this safeguard, this would be 1/4 the code.
@Termina1 I will admit though, that not having to wrap any functions before using them is very nice. Might be enough to convince me.
@Termina1, @loveencounterflow, I made another based on the syntax of suspend https://gist.github.com/creationix/5761021
TypeError: Object # < GeneratorFunctionPrototype > has no method 'send'
I am using node 0.11.3 installed Q via npm, any advice?
@txdv send is now removed from the spec. Use next(value).
https://code.google.com/p/v8/issues/detail?id=2715
@creationix Could you explain the use of sync
to detect if the callback was called before or after the continuable returned? I thought the callback will be in a later tick and sync
will always be undefined?
Yes, can you explain the logic of sync? It does not seem consistent.
Secondly, Dao007forever is correct, the callback would not be called until a later tick, so sync is not needed anyway.
callback also can be synchronous,just like
function foo(callback) {
return callback();
}
- The fact if the
sync
istrue
offalse
is never used. So, we don't needundefined
. undefined
can actually be defined in an outer scope. Always use a localvar undefined
.- When the callback was not run synchronously and we've
break
ed from the loop, we call anext
recursively. That's not a very good idea, because you can get out of stack if there're too many asynchronous callbacks in each other. I couldn't find a way to counter this issue, though. (How do we use trampolining here at all?) That's what I've been expecting to see in ES6 from the box.
EDIT. From the fact that those variables are defined outside of next
I'm guessing that you already know about (3) and you've been trying to save stack space. Haven't you?
👍 clean!