Example 1
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.
- Set variable
f
as a fiber. - Run the fiber:
- Set variable
fiber
pointing to the current running fiber. - Call function
sample
. - Call the callback.
- Call
fiber.run
, which gives the error as the current fiber is already running.
- Set variable
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:
- Set
fiber
pointing to the current running fiber. - Call
sample
, which returns without calling the callback (yet). - Call `Fiber.yield(), which 'pauses' the current fiber.
- After 500 ms, call the callback.
- Call
fiber.run()
passing 'this callback', which resumes the fiber. Fiber.yield
returns, Set str to 'this callback'.- Log the string to console.
Observe that step 4 is done outside the execution of the fiber.
Example 2
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.
The function of yield and run
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:
- An argument given to
run
(which is outside the fiber), is returned byyield
(inside the fiber). - An argument given to
yield
(inside the fiber), is returned byrun
(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
).