View
2.418
Download
2
Category
Preview:
DESCRIPTION
Introduction in asynchronous programming in Node.js, async.js, and q promises.
Citation preview
#wdc13
Put On Your Asynchronous Hat and Node
Marc Fasel @marcfasel
Shine Technologies http://blog.shinetech.com
1Saturday, 4 May 13
#wdc13
What is an Asynchronous Hat?
2Saturday, 4 May 13
#wdc13
Node.jsServer-side JavaScript platform
Event-driven, non-blocking I/O
All I/O is asynchronous
Asynchrononous everywhere
3Saturday, 4 May 13
#wdc13
Different MindsetsSynchronous coding comes natural
Natural execution order
Asynchronous coding a bit harderSerial execution leads to nesting
New: parallel execution
Single Callback functions and Event Emitters
Explicit error handling
4Saturday, 4 May 13
#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
#wdc13
Asynchronous Code
fs.readdir('/tmp/', function (err, filenames) { for (var i = 0; i < filenames.length; i++) { console.log(filenames[i]); } console.log('Done.');});
6Saturday, 4 May 13
#wdc13
Some More Synchronous Codevar 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
#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
#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
#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
#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
#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
#wdc13
Error HandlingSynchronous
Exceptions give us lots of goodies
Asynchronous Explicit error code everywhere
Lots of boilerplate
More Pyramid of Doom
13Saturday, 4 May 13
#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
#wdc13
World With Exceptionsfunction 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
#wdc13
World Before Exceptionsfunction 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
#wdc13
Asynchronous Error Handlingtry { 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
#wdc13
Callback Error Handling
fs.readFile('/tmp/test.txt', 'utf-8', function (err, data) {! if (err) return callback(err);
! // Success! console.log(data);});!
18Saturday, 4 May 13
#wdc13
Event Emitter Error Handling
var readStream = fs.createReadStream(filename);readStream.on('open', function () {! readStream.pipe(res);});readStream.on('error', function(err) { res.end(err);});
19Saturday, 4 May 13
#wdc13
Pyramid of Doom With Error Handlingfs.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){! ! ! ! ! ! ! ! ! if (err) return callback(err);! ! ! ! ! ! ! ! ! callback();! ! ! ! ! ! ! ! })! ! ! ! ! ! })! ! ! ! })! ! })});
20Saturday, 4 May 13
#wdc13
Asynchronous Error Handling
Can’t catch exceptions that happen in callbacks
Explicit code to handle error
Simple Callback: error code gets mixed with application code
Event Emitter: error code separate
21Saturday, 4 May 13
#wdc13
Help is Available
22Saturday, 4 May 13
#wdc13
Named Callbacksfs.readdir('/tmp/', readDirCallback);
function readDirCallback (err, filenames) { for (var i = 0; i < filenames.length; i++) { console.log(filenames[i]); } console.log('Done.');};
23Saturday, 4 May 13
#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
#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
#wdc13
Async.js
The Underscore.js of asynchronous code
Control flow constructs
Functional constructs
26Saturday, 4 May 13
#wdc13
Seriesasync.series([! function(callback) {! ! fs.chmod(file1,0777, function (err){! ! ! if (err) return callback(err);! ! ! callback ();! ! });! },! function(callback) {! ! fs.chmod(file2,0777, function (err){! ! ! if (err) return callback(err);! ! ! callback();! ! });! }],! function done(err) {! ! if (err) return console.log(err);! ! console.log ('Done.');! });
27Saturday, 4 May 13
#wdc13
Parallelasync.parallel([! function(callback) {! ! fs.chmod(file1,0777, function (err){! ! ! if (err) return callback(err);! ! ! callback ();! ! });! },! function(callback) {! ! fs.chmod(file2,0777, function (err){! ! ! if (err) return callback(err);! ! ! callback();! ! });! }],! function done(err) {! ! if (err) return console.log(err);! ! console.log ('Done.');! });
28Saturday, 4 May 13
#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
#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
#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
#wdc13
Promises
var readFilePromise = getReadFilePromise();
readFilePromise.then( function(data){ console.log('Resolved:' + data); }, function(err){ console.log('Rejected:' + err); });
32Saturday, 4 May 13
#wdc13
Promises
Cool Stuff: Promise Chaining
33Saturday, 4 May 13
#wdc13
Promise ChainingreadFilePromise(filePathFrom)! .then(writeFilePromise(filePathTo))! .then(changeFilePermissionPromise(filePathTo,'777'))! .then(oneMorePromise())! .then(oneMorePromise());
var promises = [! readFilePromise,! writeFilePromise,! changeFilePermissionPromise,! oneMorePromise,! oneMorePromise];
var allPromise = Q.all(promises);
34Saturday, 4 May 13
#wdc13
Promise Error Handling
readFilePromise(filePathFrom)! .then(writeFilePromise(filePathTo))! .then(changeFilePermissionPromise(filePathTo,'777'),! ! errorCallback);
35Saturday, 4 May 13
#wdc13
Promises
Promises help with asynchronous control flow
Avoid the Pyramid of Doom
Exception style error bubbling
36Saturday, 4 May 13
#wdc13
ConclusionAsynchronous programming needs an asynchronous hat
New thingsCallbacks
Event Emitters
Explicit error handling
For the more difficult stuffNamed callbacks
Async.js
Promises37Saturday, 4 May 13
#wdc13
Thank you.
38Saturday, 4 May 13
#wdc13
ReferencesTrevor 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
Recommended