Low-level fiber creation, execution control, and cooperative yielding functionality. These primitives enable building custom async abstractions and implementing synchronous-style APIs over asynchronous operations.
Creates a new fiber that executes the given function when run.
/**
* Instantiate a new Fiber. You may invoke this either as a function or as
* a constructor; the behavior is the same.
*
* When run() is called on this fiber for the first time, `fn` will be
* invoked as the first frame on a new stack. Execution will continue on
* this new stack until `fn` returns, or Fiber.yield() is called.
*
* After the function returns the fiber is reset to original state and
* may be restarted with another call to run().
*
* @param {Function} fn - Function to execute in the fiber
* @returns {Fiber} New fiber instance
*/
function Fiber(fn) { /* [native code] */ }Usage Examples:
var Fiber = require('fibers');
// Create and run a simple fiber
var fiber = Fiber(function() {
console.log('Inside fiber');
Fiber.yield('yielded value');
console.log('Resumed fiber');
return 'final value';
});
var result1 = fiber.run(); // Logs: "Inside fiber", returns: "yielded value"
var result2 = fiber.run(); // Logs: "Resumed fiber", returns: "final value"Static property containing the currently-running fiber.
/**
* `Fiber.current` will contain the currently-running Fiber. It will be
* `undefined` if there is no fiber (i.e. the main stack of execution).
*
* See "Garbage Collection" for more information on responsible use of
* `Fiber.current`.
*/
Fiber.current = undefined;Usage Examples:
function getCurrentFiber() {
if (Fiber.current) {
console.log('Running in fiber');
return Fiber.current;
} else {
console.log('Running on main stack');
return null;
}
}
Fiber(function() {
var current = getCurrentFiber(); // Returns the current fiber
}).run();
getCurrentFiber(); // Returns nullHalts execution of the current fiber and returns control back to the caller.
/**
* `Fiber.yield()` will halt execution of the current fiber and return control
* back to original caller of run(). If an argument is supplied to yield(),
* run() will return that value.
*
* When run() is called again, yield() will return.
*
* Note that this function is a global to allow for correct garbage
* collection. This results in no loss of functionality because it is only
* valid to yield from the currently running fiber anyway.
*
* Note also that `yield` is a reserved word in Javascript. This is normally
* not an issue, however some code linters may complain. Rest assured that it
* will run fine now and in future versions of Javascript.
*
* @param {*} param - Optional value to return to caller
* @returns {*} Value passed to next run() call
*/
Fiber.yield = function(param) { /* [native code] */ }Usage Examples:
// Incremental generator example
var inc = Fiber(function(start) {
var total = start;
while (true) {
total += Fiber.yield(total);
}
});
for (var ii = inc.run(1); ii <= 10; ii = inc.run(1)) {
console.log(ii); // Prints: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
}Starts or resumes fiber execution.
/**
* run() will start execution of this Fiber, or if it is currently yielding,
* it will resume execution. If an argument is supplied, this argument will
* be passed to the fiber, either as the first parameter to the main
* function [if the fiber has not been started] or as the return value of
* yield() [if the fiber is currently yielding].
*
* This function will return either the parameter passed to yield(), or the
* returned value from the fiber's main function.
*
* @param {*} param - Optional parameter to pass to fiber
* @returns {*} Value passed to yield() or fiber return value
*/
Fiber.prototype.run = function(param) { /* [native code] */ }Terminates a running fiber and restores it to its original state.
/**
* reset() will terminate a running Fiber and restore it to its original
* state, as if it had returned execution.
*
* This is accomplished by causing yield() to throw an exception, and any
* futher calls to yield() will also throw an exception. This continues
* until the fiber has completely unwound and returns.
*
* If the fiber returns a value it will be returned by reset().
*
* If the fiber is not running, reset() will have no effect.
*
* @returns {*} Return value from fiber if any
*/
Fiber.prototype.reset = function() { /* [native code] */ }Usage Examples:
var fiber = Fiber(function() {
try {
while (true) {
Fiber.yield('continuing');
}
} catch (e) {
console.log('Fiber was reset');
return 'cleaned up';
}
});
fiber.run(); // Returns: 'continuing'
var result = fiber.reset(); // Logs: "Fiber was reset", returns: 'cleaned up'Causes a yielding fiber's yield() call to throw instead of return.
/**
* throwInto() will cause a currently yielding fiber's yield() call to
* throw instead of return gracefully. This can be useful for notifying a
* fiber that you are no longer interested in its task, and that it should
* give up.
*
* Note that if the fiber does not handle the exception it will continue to
* bubble up and throwInto() will throw the exception right back at you.
*
* @param {Error} exception - Exception to throw in fiber
*/
Fiber.prototype.throwInto = function(exception) { /* [native code] */ }Usage Examples:
var fiber = Fiber(function() {
try {
Fiber.yield('yielding');
console.log('This will not execute');
} catch (e) {
console.log('Caught exception:', e.message);
return 'handled error';
}
});
fiber.run(); // Returns: 'yielding'
var result = fiber.throwInto(new Error('Stop processing'));
// Logs: "Caught exception: Stop processing", returns: 'handled error'Fibers are exception-safe; exceptions will continue travelling through fiber boundaries:
var fn = Fiber(function() {
console.log('async work here...');
Fiber.yield();
console.log('still working...');
Fiber.yield();
console.log('just a little bit more...');
Fiber.yield();
throw new Error('oh crap!');
});
try {
while (true) {
fn.run();
}
} catch(e) {
console.log('safely caught that error!');
console.log(e.stack);
}Fiber.current without proper cleanupyield() to throw when necessary