Just to add a slightly shorter/arguably cleaner example for using the *async* module (if using waterfall, embrace that it's a waterfall!):
CDN.use(config.CDN.baseUrl, function(req, res, next) { var req_path = config.base+"/cdn"+req.url; async.waterfall([ fs.lstat.bind(fs, req_path), function (stats, cb) { if (!stats.isSymbolicLink()) { return next(); } cb(req_path); }, fs.readlink, fs.readFile, function (data) { res.writeHead(200,{"Content-type":"text/html"}); res.end(data); } ], next); }); I've spent most of my time in Node writing high performance network layers and related things and less time writing the "business logic", so I prefer to write as close to the metal as possible, mostly so that I can look at code and know at a glance what the async steps are, and I find this rather readable. Additionally, when really trying to get the most performance, things like closures or .bind calls (which allocate memory that won't get collected in the early/quick generational garbage collection if your async tasks take any significant amount of time) are to be avoided (irrelevant in this case, since file I/O is going to have so much more overhead than anything you could possibly change syntactically here). However, there's a pretty big barrier to entry here - getting a new (perhaps not as awesome as all of you) person to a team asynchronous Javascript code, they can be incredibly baffled (though, usually, only when it gets to things like loops, not for simple chained stuff like the examples in this thread). I suspect that if I had them use streamline instead, I would have spent a lots less time unravelling the first async code they wrote (admittedly, once they've done an async loop themselves a couple times to understand it, and then learn how to write it much more succinctly with the *async* module, they're generally fine after that). Also, assuming we want what the original posted requested (middleware that just handles symlinks, leaving regular files alone to the rest of his stack), the streamline version, I think, looks like this: CDN.use(config.CDN.baseUrl, function(req, res, next, _) { var path = config.base + "/cdn" + req.url; if (!fs.lstat(path, _).isSymbolicLink()) { return next(); } path = fs.readlink(path, _); res.writeHead(200, { "Content-type" : "text/html" }); res.end( fs.readFile(path, _)); }); Though, as someone very familiar with the pitfalls of Javascript, and very unfamiliar with streamline, I'd have to look at the generated code to assure myself that's actually doing what I think I want it to, as I could imagine many ways in which that code could be converted to raw asynchronous code incorrectly (I'll assume for now it's smart enough and does it right ; ). Jimb Esser On Tuesday, September 23, 2014 4:29:46 AM UTC-7, Alexey Petrushin wrote: > > Ha-ha, very good example, compare this async version it with the sync > version below, and tell me that there's no problem with > callbacks """if you know how to deal with it""" :D > > Not saying that in even such a simple code it's extremely > easy to make small errors like missing `else` statements etc. > > Also it doesn't preserve the call stack - so when you see error in console > you would have no context and no idea what happened... > And it still doesn't catch the sync errors... > And some of callbacks can be fired twice... > And with streams there are lots of events fired and should be properly > handled... > > And still many insist that it is "not a problem". > > CDN.use(config.CDN.baseUrl, function(req, res, next) { > if(err) return next(err); > async.waterfall([ > function (cb) { > fs.lstat(config.base+"/cdn"+req.url, cb); > }, > function (stats, cb) { > if(stats.isSymbolicLink()) { > async.waterfall([ > function (cb) { > fs.readlink(config.base+"/cdn"+req.url, cb); > }, > function (linkstr, cb) { > log.info("Redirecting request \""+req.url+"\" > to \""+linkstr); > fs.readFile(linkstr, cb); > }, > ], cb); > } > } > ], function (err, data) { > if (err) return next(err); > res.writeHead(200,{"Content-type":"text/html"}); > res.end(data); > }); > }); > > Sync version. > > CDN.use(config.CDN.baseUrl, function(req, res, next) { > var stats = fs.lstat(config.base+"/cdn"+req.url) > if(stats.isSymbolicLink()) { > var linkstr = fs.readlink(config.base+"/cdn"+req.url); > log.info("Redirecting request \""+req.url+"\" to \""+linkstr); > var data = fs.readFile(linkstr); > res.writeHead(200,{"Content-type":"text/html"}); > res.end(data); > } > }); > > On Monday, 22 September 2014 05:18:40 UTC+4, Matt Sergeant wrote: >> >> >> On Sat, Sep 20, 2014 at 9:17 AM, Bruno Jouhier <bjou...@gmail.com> wrote: >> >>> How do you implement it with async? >> >> >> This is a good question, so here's an example translation (not the only >> way to do it): >> >> >> CDN.use(config.CDN.baseUrl, function(req, res, next) { >> if(err) return next(err); >> async.waterfall([ >> function (cb) { >> fs.lstat(config.base+"/cdn"+req.url, cb); >> }, >> function (stats, cb) { >> if(stats.isSymbolicLink()) { >> async.waterfall([ >> function (cb) { >> fs.readlink(config.base+"/cdn"+req.url, cb); >> }, >> function (linkstr, cb) { >> log.info("Redirecting request >> \""+req.url+"\" to \""+linkstr); >> fs.readFile(linkstr, cb); >> }, >> ], cb); >> } >> } >> ], function (err, data) { >> if (err) return next(err); >> res.writeHead(200,{"Content-type":"text/html"}); >> res.end(data); >> }); >> }); >> >> It's more code, but it improves the error checking. If it didn't have >> that "if" statement in there it would be a lot simpler - async code doesn't >> deal well with "if" statements I've found (there's no way to short-circuit). >> >> Matt. >> > -- Job board: http://jobs.nodejs.org/ New group rules: https://gist.github.com/othiym23/9886289#file-moderation-policy-md Old group rules: https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines --- You received this message because you are subscribed to the Google Groups "nodejs" group. To unsubscribe from this group and stop receiving emails from it, send an email to nodejs+unsubscr...@googlegroups.com. To post to this group, send email to nodejs@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/nodejs/bdfcf7e8-6316-4f07-a714-9407402df65b%40googlegroups.com. For more options, visit https://groups.google.com/d/optout.