If you’re get used to synchronized way of coding with using threading, etc. and you go into environment like node.js, you’re exposed to an enormous usage of callback practically all the time. By practicing you will be able to read it but in general it’s not very transparent because it’s harder to follow flow and it can lead to “pyramid-code” and “callback hell”.
Fibers are one way how to give your code more synchronized look without changing asynchronous nature.
Callback
Let’s start with a usual callback way. We have code that triggers some long running code (simulated with setTimeout here).
function doSomethingTimeConsuming(description, callback) {
setTimeout(function() {
callback && callback(null, 'result for ' + description);
}, 1000);
}
function doSomething (description) {
console.log(description + ' initiated');
doSomethingTimeConsuming(description, function(err, res) {
console.log(description + ' done with result ' + res);
});
}
doSomething('first long-time job');
doSomething('second long-time job');
console.log('All commands given');
When we execute it we will get output below.
This is a quite common style and it doesn’t look that bad until we have more complicated code where pyramid scheme occurs. Anyway it would be nice to get rid with all callbacks.
Sync style in async environment
This is something what would be desired:
function doSomethingTimeConsuming(description) {
setTimeout(function() {
var result = 'result for ' + description;
return result; }, 1000);
}
function doSomething (description) {
console.log(description + ' initiated');
var result = doSomethingTimeConsuming(description);
console.log(description + ' done with result ' + res);
}doSomething('first long-time job');
doSomething('second long-time job');
console.log('All commands given');
This obviously will not work as the results are not known when evaluated.
Fibers
Fibers allows us to wrap the code to write it like synchronized block but without blocking others. But it’s not for free (at least in terms of coding). We need to to additional changes.
- require “fibers” library (1)
- create fiber variable in long-running function(2)
- pass result to fiber (3)
- fiber must yield until result is given not to block others (4)
- wrap and run request into Fiber (5)
var Fiber = require('fibers'); // (1)
function doSomethingTimeConsuming(description) {
var fiber = Fiber.current; // (2)
setTimeout(function() {
fiber.run('result for ' + description); //(3)
}, 1000);
var results = Fiber.yield(); //(4)
return results;
}
function doSomething (description) {
Fiber(function() { // (5)
console.log(description + ' initiated');
var result = doSomethingTimeConsuming(description);
console.log(description + ' done with result ' + result);
}).run();
}
doSomething('first long-time job');
doSomething('second long-time job');
console.log('All commands given');
Now the code works as expected with eliminating all callbacks.
Fibers are possible way but every one must decide when it’s worth to use it or to use callback or another library like Async, Step, Syncify or wait to async in ES7.
For the LORD has called you back from your grief — as though you were a young wife abandoned by her husband,” says your God. (Isaiah 54:6)