4. #wdc13
Different Mindsets
Synchronous coding comes natural
Natural execution order
Asynchronous coding a bit harder
Serial execution leads to nesting
New: parallel execution
Single Callback functions and Event Emitters
Explicit error handling
4Saturday, 4 May 13
5. #wdc13
Synchronous Code
var filenames = fs.readdirSync('/tmp/');
for (var i = 0; i < filenames.length; i++) {
console.log(filenames[i]);
}
console.log('Done.');
5Saturday, 4 May 13
7. #wdc13
Some More Synchronous Code
var totalBytes = 0;
for (var i = 0; i < filenames.length; i ++) {
var stats = fs.statSync('/tmp/' + filenames[i]);
totalBytes += stats.size;
}
console.log('Total bytes: ' + totalBytes);
7Saturday, 4 May 13
8. #wdc13
Asynchronous Parallel Execution
var count = filenames.length;
for (var i = 0; i < filenames.length; i++) {
! fs.stat('/tmp/' + filenames[i], function (err, stats) {
! ! totalBytes += stats.size;
! ! count--;
! ! if (count === 0) {
! ! ! // We’re done
! ! ! console.log('Total bytes: ' + totalBytes);
! ! }
! });
};
8Saturday, 4 May 13
9. #wdc13
fs.readFile(dirFrom+filename,'utf-8', function (err, data){
! ! if (err) return callback(err);
! ! fs.writeFile(dirTo+filename,data,'utf-8', function (err){
! ! ! ! if (err) return callback(err);
! ! ! ! fs.chmod(dirTo+filename,0777, function (err){
! ! ! ! ! ! if (err) return callback(err);
! ! ! ! ! ! anotherAsyncFunction(param1, function (err){
! ! ! ! ! ! ! ! if (err) return callback(err);
! ! ! ! ! ! ! ! anotherAsyncFunction(param1, function (err){
! ! ! ! ! ! ! ! })
! ! ! ! ! ! })
! ! ! ! })
! ! })
});
Pyramid of Doom
9Saturday, 4 May 13
10. #wdc13
Event Mechanisms
Events used for asynchronous communication
Two types of asynchronous functions:
Single Callback: one ‘done’ event, single callback function
Event Emitter: more than one event
10Saturday, 4 May 13
11. #wdc13
Single Callback Functions
fs.readdir(dir, function (err, filenames) {
// Failure
! if (err) return callback(err);
// Success
! console.log(dir + ' has ' + filenames.length + 'files.');
});!
11Saturday, 4 May 13
12. #wdc13
Event Emitter
var readStream = fs.createReadStream(filename);
readStream.on('open', function () {
! readStream.pipe(res);
});
readStream.on('error', function(err) {
! // Failure
! res.end(err);
});
12Saturday, 4 May 13
14. #wdc13
Synchronous Error Handling
We are blessed with Exceptions
Stop execution immediately
Automatically bubble up call hierarchy
Error code logically separated from application code
14Saturday, 4 May 13
15. #wdc13
World With Exceptions
function readFile(fileName) {
! var file = openFile(fileName);
! var data = readContent(file);
! closeFile(file);
! return data;
}
function readContent(file) {
! throw new Error("Exception!");
}
try {
! var myData = readFile(fileName);
} catch (e) {
! // Handle error!
}
15Saturday, 4 May 13
16. #wdc13
World Before Exceptions
function readFile(err, filePath) {
! var file = openFile(err, filePath);
! if (err) { return err; }
! var data = readContent(err, file);
! if (err) { return err;}
! closeFile(err, file);
! if (err) { return err; }
! return data;
}
var myFileContent = readFile(err,filePath);
if (err) { // Handle error };
16Saturday, 4 May 13
17. #wdc13
Asynchronous Error Handling
try {
fs.readFile('/tmp/test.txt', 'utf-8', function (err, data) {
!if (err) {
!! throw err;
!}
console.log(data);
});!
} catch (e) {
! console.log(e);
}
Exceptions possible
try/catch does not have desired result
17Saturday, 4 May 13
24. #wdc13
Nesting Named Callbacks
function copyFile(filePathFrom, filePathTo, callback){
! fs.readFile(filePathFrom,'utf-8', readFileCallback);
! function readFileCallback(err, data){
! ! if (err) return callback(err);
! ! fs.writeFile(filePathTo, data, 'utf-8', writeFileCallback);
! ! function writeFileCallback(err){
! ! ! if (err) return callback(err);
! ! ! callback();
! ! };
! };
};
24Saturday, 4 May 13
25. #wdc13
Control Flow libraries
Fix problems with asynchronous Control Flow
Control flow first thing people want to fix
Many control flow libraries available
25Saturday, 4 May 13
29. #wdc13
Functional Constructs
async.map(['file1','file2','file3'], fs.stat, function(err, results){
// results is now an array of stats for each file
});
async.filter(['file1','file2','file3'], path.exists, function(results){
// results now equals an array of the existing files
});
async.reduce(...);
29Saturday, 4 May 13
30. #wdc13
Promises
Pattern for asynchronous control flow
Promises are objects representing a future outcome of an
asynchronous call
Outcome will be either ‘resolved’ or ‘rejected’
Attach callbacks to ‘resolved’, ‘rejected’
30Saturday, 4 May 13
31. #wdc13
Callback -> Promise
function getReadFilePromise(){
! var deferred = q.defer();
! fs.readFile('/tmp/test.txt', 'utf-8', function (err, data) {
! ! if (err) { deferred.reject(err); }
! ! deferred.resolve(data);
! });! !
! return deferred.promise;
}
31Saturday, 4 May 13
36. #wdc13
Promises
Promises help with asynchronous control flow
Avoid the Pyramid of Doom
Exception style error bubbling
36Saturday, 4 May 13
37. #wdc13
Conclusion
Asynchronous programming needs an asynchronous hat
New things
Callbacks
Event Emitters
Explicit error handling
For the more difficult stuff
Named callbacks
Async.js
Promises
37Saturday, 4 May 13
39. #wdc13
References
Trevor Burnham - Async JavaScript: Build More Responsive Apps with
Less Code
Pedro Teixeira - Professional Node.js: Building Javascript-Based
Scalable Software
You’re Missing the Point of Promises - http://domenic.me/2012/10/14/
youre-missing-the-point-of-promises/
Popular Control Flow Libraries - http://dailyjs.com/2011/11/14/popular-
control-flow/
39Saturday, 4 May 13