Promise-like abstraction that wraps fiber operations in a more familiar async/await-style interface. The Future API is designed to make it easy to move between classic callback-style code and fiber-aware waiting code, making it ideal for converting Node.js callback-based APIs to synchronous-style code.
Creates a new Future object for async operations.
/**
* Future object, instantiated with the new operator.
*/
function Future() {}Usage Examples:
var Future = require('fibers/future');
// Create and manually resolve a future
var future = new Future();
setTimeout(function() {
future.return('resolved value');
}, 1000);
// In a fiber context, wait for resolution
Future.task(function() {
var result = future.wait(); // Blocks fiber until resolved
console.log(result); // 'resolved value'
}).detach();Converts functions to return futures when called.
/**
* Returns a future-function which, when run, starts running the target
* function and returns a future for the result.
*
* @param {boolean} detach - Optional. If true, automatically calls detach() on the returned future
* @returns {Function} Function that returns futures when called
*
* Example usage:
* var funcy = function(arg) {
* return arg+1;
* }.future();
*
* funcy(1).wait(); // returns 2
*
* // With detach parameter - runs in background without need to wait
* var backgroundTask = function() {
* console.log('Background work');
* }.future(true); // Auto-detaches
*
* backgroundTask(); // Runs in background, doesn't need .wait()
*/
Function.prototype.future = function(detach) { /* ... */ }Usage Examples:
// Convert function to return futures
var asyncAdd = function(a, b) {
return a + b;
}.future();
Future.task(function() {
var result = asyncAdd(5, 3).wait(); // Returns: 8
console.log(result);
}).detach();Runs functions in fiber context and returns futures to their return values.
/**
* Invoke a function that will be run in its own fiber context and return a future to its return
* value.
*
* @param {Function} fn - Function to run in fiber context
* @returns {Future} Future resolving to function's return value
*
* Example:
* Future.task(function() {
* // You can safely `wait` on stuff here
* }).detach();
*/
Future.task = function(fn) { /* ... */ }Usage Examples:
// Simple task execution
Future.task(function() {
console.log('Running in fiber');
return 'task result';
}).resolve(function(err, val) {
if (err) throw err;
console.log(val); // 'task result'
});Wraps node-style async functions to return futures instead of using callbacks.
/**
* Wrap a node-style async function to return a future in place of using a callback.
*
* @param {Function|Object} fn - The function or object to wrap
* @param {boolean} multi - Indicates callback returns more than 1 argument after `err`
* @param {string} suffix - Appends string to every wrapped method name (default: 'Future')
* @param {boolean} stop - Internal parameter to prevent recursive wrapping
* @returns {Function|Object} Future-returning function or wrapped object
*
* Example usage: Future.wrap(asyncFunction)(arg1).wait()
*/
Future.wrap = function(fn, multi, suffix, stop) { /* ... */ }Usage Examples:
var fs = Future.wrap(require('fs'));
Future.task(function() {
// Synchronous-style file operations
var files = fs.readdirFuture('.').wait();
console.log('Found ' + files.length + ' files');
var content = fs.readFileFuture('package.json').wait();
console.log('Package.json content:', content.toString());
}).detach();Waits for multiple futures to resolve.
/**
* Wait on a series of futures and then return. If the futures throw an exception this function
* /won't/ throw it back. You can get the value of the future by calling get() on it directly. If
* you want to wait on a single future you're better off calling future.wait() on the instance.
*
* Example usage: Future.wait(aFuture, anotherFuture)
*/
Future.wait = function(/* ... */) { /* ... */ }Usage Examples:
Future.task(function() {
var fs = Future.wrap(require('fs'));
// Start multiple async operations
var file1 = fs.readFileFuture('file1.txt');
var file2 = fs.readFileFuture('file2.txt');
var file3 = fs.readFileFuture('file3.txt');
// Wait for all to complete
Future.wait(file1, file2, file3);
// Get results
console.log('File 1:', file1.get().toString());
console.log('File 2:', file2.get().toString());
console.log('File 3:', file3.get().toString());
}).detach();Converts between Futures and ES6 Promises.
/**
* Returns a Future that waits on an ES6 Promise.
* @param {Promise} promise - ES6 Promise to convert
* @returns {Future} Future that resolves when promise resolves
*/
Future.fromPromise = function(promise) { /* ... */ }/**
* Return the value of this future. If the future hasn't resolved yet this will throw an error.
* @returns {*} The resolved value
* @throws {Error} If future is not resolved or was rejected
*/
Future.prototype.get = function() { /* ... */ }/**
* Mark this future as returned. All pending callbacks will be invoked immediately.
*
* @param {*} value - The value to return when get() or wait() is called
*
* Example usage: aFuture.return(value)
*/
Future.prototype.return = function(value) { /* ... */ }
/**
* Throw from this future as returned. All pending callbacks will be invoked immediately.
* Note that execution will continue normally after running this method,
* so make sure you exit appropriately after running throw()
*
* @param {Error} error - The error to throw when get() or wait() is called
*
* Example usage: aFuture.throw(new Error("Something borked"))
*/
Future.prototype.throw = function(error) { /* ... */ }/**
* Returns whether or not this future has resolved yet.
* @returns {boolean} True if resolved, false otherwise
*/
Future.prototype.isResolved = function() { /* ... */ }
/**
* "detach" this future. Basically this is useful if you want to run a task in a future, you
* aren't interested in its return value, but if it throws you don't want the exception to be
* lost. If this fiber throws, an exception will be thrown to the event loop and node will
* probably fall down.
*/
Future.prototype.detach = function() { /* ... */ }/**
* Returns a node-style function which will mark this future as resolved when called.
*
* @returns {Function} Node-style callback (err, val) => void
*
* Example usage:
* var errback = aFuture.resolver();
* asyncFunction(arg1, arg2, etc, errback)
* var result = aFuture.wait();
*/
Future.prototype.resolver = function() { /* ... */ }
/**
* Waits for this future to resolve and then invokes a callback.
*
* If only one argument is passed it is a standard function(err, val){} errback.
*
* If two arguments are passed, the first argument is a future which will be thrown to in the case
* of error, and the second is a function(val){} callback.
*
* @param {Function|Future} arg1 - Errback function or future for error propagation
* @param {Function} arg2 - Success callback (if first arg is a future)
* @returns {Future} This future for chaining
*/
Future.prototype.resolve = function(arg1, arg2) { /* ... */ }/**
* Propogate results to another future.
*
* @param {Future} future - Target future to propagate results to
*
* Example usage: future1.proxy(future2) // future2 gets automatically resolved with however future1 resolves
*/
Future.prototype.proxy = function(future) { /* ... */ }
/**
* Propogate only errors to an another future or array of futures.
*
* @param {Future|Future[]} futures - Target future(s) for error propagation
* @returns {Future} This future for chaining
*/
Future.prototype.proxyErrors = function(futures) { /* ... */ }/**
* Returns an ES6 Promise
* @returns {Promise} ES6 Promise that resolves when this future resolves
*/
Future.prototype.promise = function() { /* ... */ }/**
* Differs from its functional counterpart in that it actually resolves the future. Thus if the
* future threw, future.wait() will throw.
* @returns {*} The resolved value
* @throws {Error} If future was rejected
*/
Future.prototype.wait = function() { /* ... */ }var Future = require('fibers/future');
var fs = Future.wrap(require('fs'));
Future.task(function() {
// Get list of files
var fileNames = fs.readdirFuture('.').wait();
console.log('Found ' + fileNames.length + ' files');
// Stat each file in parallel
var stats = [];
for (var ii = 0; ii < fileNames.length; ++ii) {
stats.push(fs.statFuture(fileNames[ii]));
}
// Wait for all stats to complete
stats.map(function(f) { f.wait(); });
// Print file sizes
for (var ii = 0; ii < fileNames.length; ++ii) {
console.log(fileNames[ii] + ': ' + stats[ii].get().size);
}
}).detach();// Create custom async operation using Future
function sleep(ms) {
var future = new Future();
setTimeout(function() {
future.return();
}, ms);
return future;
}
// Use with automatic fiber execution
var calcTimerDelta = function(ms) {
var start = new Date();
sleep(ms).wait();
return new Date() - start;
}.future();
// Get result with callback
calcTimerDelta(2000).resolve(function(err, val) {
console.log('Set timer for 2000ms, waited ' + val + 'ms');
});