O'Reilly

Synchronous Exec in Node.js

By on  

Everyone loves NodeJS in part because it embraces a non-blocking philosophy;  interactions are asynchronous and thus, theoretically, allow for faster all-around processing.  When creating a simple script for my upcoming redesign, I found the asynchronocity ... annoying.  I was quickly sinking into callback hell with the server executions I was running through Node.js.  Luckily I found a great package called exec-sync which allows synchronous execution of shell commands so that I don't find myself many callbacks deep.

Installing exec-sync

The exec-sync package is available via npm:

npm install exec-sync

Don't you love package management?!

Using execSync

exec-synce works like any other Node.js component;  require it and it's ready to use:

// Require the dependency
var execSync = require("exec-sync");

// The traditional way
var exec = require('child_process').exec;
exec('ORIGINAL COMMAND', function(err, stdout, stderr) {
	// React to callback

	exec('SOME OTHER COMMAND', function(err2, stdout2, stderr2) {
		// More reacting

		// ... more nesting that isn't desired
	});
});

// The execSync way

var execSync = require("exec-sync");

// Create the JavaScript dir, uglify contents
execSync("cp -R "  + sourceDir + "js " + jsDir);
doCompress && walkAndDo("js", jsDir, function(fileName, stat) {
	execSync("./node_modules/uglify-js/bin/uglifyjs -nc --reserved-names 'require,define,curl,z' --unsafe --lift-vars --overwrite " + fileName);
});

// Copy the "crons" and "cache" directories over
execSync("cp -R " + sourceDir + "crons " + dirPath + "crons");
execSync("cp -R " + sourceDir + "cache " + dirPath + "cache");

// Delete all bullshit ".DS_Store" files
execSync("find . -type f -name .DS_Store -exec rm -rf {} +");

// And when all is done, copy to another place
execSync("mv " + dirPath + " ../../../wp-content/themes/jack"); 

Note that instead of passing a callback to the execSync method, I can simply assume things are running from the top down, allowing me to avoid a bunch of nested callbacks that would only muddy up my code.  Of course some processes could be asynchronous but exec-sync allows me to keep a top-down thought process. Node.js does have utilities for a few of these functions, but running shell keeps the code shorter.

The code above was just a tiny snippet of my build file. Without exec-sync, I would either need to nest and nest and nest callbacks, or get a Deferred implementation to handle all the callbacks. Using a Deferred implementation would allow for more speed for the build process, but when the process takes only a few seconds, the tradeoff for top-down execution is worth it.

Track.js Error Reporting

Upcoming Events

Recent Features

  • 7 Essential JavaScript Functions

    I remember the early days of JavaScript where you needed a simple function for just about everything because the browser vendors implemented features differently, and not just edge features, basic features, like addEventListener and attachEvent.  Times have changed but there are still a few functions each developer should...

  • An Interview with Eric Meyer

    Your early CSS books were instrumental in pushing my love for front end technologies. What was it about CSS that you fell in love with and drove you to write about it? At first blush, it was the simplicity of it as compared to the table-and-spacer...

Incredible Demos

Discussion

  1. Brusselsblogger

    A few days ago I also tried to find a solution to the sometimes annoying asynchronous way of how code is executed in node.js.

    I then discovered that there are a multitude of solutions to deal with flow control in node.js (one being exec-sync).

    After some research I decided to go with https://github.com/kriskowal/q/ as it is one of the most popular and complete module. I like the concept of “promises” and it turns out that jQuery has a similar technique with it deferred object. For me, promises were difficult to understand, but this article helped a lot: http://erickrdch.com/2012/06/how-to-wait-for-2-asynchronous-responses-on-nodejs-commonjs-promises.html

  2. Artem

    Sorry ^^. Here is the link to formated code:

    http://pastebin.com/LkyKZi80

  3. David

    Been hearing a lot about NodeJS recently. Seems like something worth picking up. I’m a server-end developer, so my experiences with front-end developing are fleeting. =)

    Also worth note is… well… a note. On jQuery’s AJAX page: http://api.jquery.com/jQuery.ajax/
    “As of jQuery 1.8, the use of async: false with jqXHR ($.Deferred) is deprecated; you must use the complete/success/error callbacks.”

    Seems like synchronous ajax calls are out the door for jQuery at the moment.

  4. You don’t want to do this; it does separate concerns.

  5. I think there’s some confusion here. I know how to hand asynchronous actions and I’m well aware of Deferreds in Dojo and jQuery.

    My point with this post is that there are times when synchronous, top-down execution is preferred.

  6. Billy Moon

    after installing (and calling) execSync, I get warning in my code output:

    “Utf8String” type is deprecated, use “CString” instead

    Version installed…

    [email protected] ../../../../../../node_modules/exec-sync
    └── [email protected] ([email protected], [email protected], [email protected], [email protected])

  7. This saves the stdout to a tmp/file then reads it back correct? I guess as long as this is used for build files this should be good (according to the stackoverflow people)

  8. naikrovek

    > npm install exec-sync

    if only it were that easy. I just tried it on three machines, all with python and visual studio, and it failed on each one.

    Maintainers of this and execSync need better software, or better software documentation.

  9. Mark

    I too have failed to install. It seems even with python and .net that this npm still fails. First time I’ve had such a hard time installing too.

  10. Coder

    The exec-sync is and has been working fine. Grow a pair and unwad your panties ;)

  11. You can have your cake and eat it, too — with coroutines. Check out generators, available since Node 0.11.

  12. Another approach to this is run a sequence of commands over a spawned shell that stays alive across many commands all executed sequentially (using streams to interact with it) such as https://github.com/bitsofinfo/stateful-process-command-proxy

  13. Antiquated and no longer valid advice. See this question on StackOverflow for an uptodate solution that uses the standard library.. http://stackoverflow.com/q/31819950/124486

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!

Recently on David Walsh Blog

  • Intercept HTTP Requests with Node.js nock

    Unit testing external APIs is difficult no matter what language you do it in.  Hell, working with any external API is scary, if only because you have zero control of networking issues, API changes, and a host of other issues.  But if you do create a service...

  • Introducing Frontend Masters (with Giveaway)

    Hey DWB readers, I'm super happy to sponsor this blog. I've been a long-time reader and fan, since back when David wrote about JavaScript and MooTools back in 2007. ;-) We are in one of the fastest changing, evolving, most lively communities on earth: JavaScript and front-end web...

  • Get Node.js Command Line Arguments with yargs

    Using command line arguments within Node.js apps is par for the course, especially when you're like me and you use JavaScript to code tasks (instead of bash scripts).  Node.js provides process.argv but that doesn't provide a key: value object like you'd expect: Bleh.  If you want to work with a...

  • OâReilly Velocity Conference â New York

    My favorite front-end conference has always been O'Reilly's Velocity Conference because the conference series has focused on one of the most undervalued parts of client side coding:  speed.  So often we're so excited that our JavaScript works that we forget that speed, efficiency, and performance are just as important. The next Velocity...

  • Free Download: Font Bundle Featuring 17 Incredible Typefaces

    The only thing we love more than a good font, is a good free font. So we’ve combed the Web for some of our favorite free fonts, and gathered them here in a single download. You’ll find a variety of useful typefaces, from highly geometric designs...