I have a question about Nodejs Fibers(which is absolute new for me) ... I have this tutorial for Nodejs Fibers, http://bjouhier.wordpress.com/2012/03/11/fibers-and-threads-in-node-js-what-for/, and there was an example in here it says
var fiber = Fiber.current;
db.connect(function(err, conn) {
if (err) return fiber.throwInto(err);
fiber.run(conn);
});
// Next line will yield until fiber.throwInto
// or fiber.run are called
var c = Fiber.yield();
// If fiber.throwInto was called we don't reach this point
// because the previous line throws.
// So we only get here if fiber.run was called and then
// c receives the conn value.
doSomething(c);
// Problem solved!
Now based on this Example I created my own version of the code like this,
var Fiber = require('fibers');
function sample(callback){
callback("this callback");
}
var fiber = Fiber.current;
sample(function(string){
fiber.run(string);
});
var string = Fiber.yield();
console.log(string);
but this gives me an Error of,
/home/ubuntu/Tasks/ServerFilteringV1/test.js:28
fiber.run(string);
^
TypeError: Cannot call method 'run' of undefined
And I have another case which will run a function after 1000 ms with the callback inside (I have done this to test functions with long time executions before a callback),
var Fiber = require('fibers');
function forEach(callback){
setTimeout(function(){
callback("this callback");
},1000);
}
var fiber = Fiber.current;
forEach(function(string){
fiber.run(string);
});
var string = Fiber.yield();
console.log(string);
This code in here gives me another Error ,
/home/ubuntu/Tasks/ServerFilteringV1/test.js:30
var string = Fiber.yield();
^
Error: yield() called with no fiber running
Well, should the yield() wait after a run() function is executed? Any idea about what is happening in my nodejs code? And thanks in advance ...
A fiber is a sort of lightweight thread of execution. Like real threads and processes, a fiber must be given a block of code to execute upon run. The code as you took it from bjouhier does not work as is. It was intended to run inside a fiber, like so:
var f = Fiber(function() {
var fiber = Fiber.current;
sample(function(str) {
fiber.run(string);
});
var str = Fiber.yield();
console.log(str);
});
f.run();
Calling run
on the fiber, well, runs the fiber code, which was given as callback to Fiber
. The above code, however, will also give an error (stating the fiber is already running). One might easily see why when analysing the order of execution.
f
as a fiber.fiber
pointing to the current running fiber.sample
.fiber.run
, which gives the error as the current fiber is already running.The structure of this code is correct, but it assumes sample
is some asynchronous function that does not immediately call the callback. Let's swap out your sample
function by this one:
function sample(callback) {
setTimeout(function() {
callback("this callback");
}, 500);
}
Now, the above code won't emit an error, as sample
immediately returns. The order of execution inside the fiber is:
fiber
pointing to the current running fiber.sample
, which returns without calling the callback (yet).fiber.run()
passing 'this callback', which resumes the fiber.Fiber.yield
returns, Set str to 'this callback'.Observe that step 4 is done outside the execution of the fiber.
Whereas in the first example there was no running fiber (and therefore fiber
was undefined), in the second example the error is thrown for the same reason. Again, the code needs to run inside a fiber.
A fiber must cooperatively give control to another fiber (or the main line of execution). Compare that to the preemptive nature of threads and processes. The giving up control is what is meant by 'yielding control', and in this case is done by Fiber.yield()
.
To continue execution (directly after the point of where the fiber yielded), one must call run()
on the fiber.
The mechanism to pass values in and out of the fiber is through the interplay of yield and run:
run
(which is outside the fiber), is returned by yield
(inside the fiber).yield
(inside the fiber), is returned by run
(outside the fiber).For an example, look at the incremental generator on the github repository of node-fibers. Additionally, observe that our Example 1, the callback given to sample
is essentially ran outside the fiber, as it is ran on the next tick (viz. the async nature of setTimeout
).