Earlier quoted context omitted.
I think you have it wrong, generators would solve the problem. If you have asynchronous code N call layers down, then everything above it would be asynchronous as well. So you would only need to yield the first call. Check how Q.nfcall works.
That's a faulty assertion. A generators working principle is that it can resume into the closure if the "caller" is looping over the generator. Let's assume a simple call stack, A -> B -> C. Now C would be a generator, so B has to loop over C instead of just calling C. But what about A? Well if B is now looping, and if yielding out of a loop is how you cooperatively multitask, then A now has to loop over B. So you ha…
But let me give you an example, again with Q.nfcall.
MultiplyAndSquare = (a, b, cb) ->
Multiply a, b, (err, product) ->
Square product, (err, square) ->
cb null, square #ignore errors for now.
nonCallbackVersion = (a, b) -> Q.nfcall(MultiplyAndSquare, a, b)
result = yield nonCallbackVersion(10, 20)