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

  • 6 Things You Didn’t Know About Firefox OS

    Firefox OS is all over the tech news and for good reason:  Mozilla's finally given web developers the platform that they need to create apps the way they've been creating them for years -- with CSS, HTML, and JavaScript.  Firefox OS has been rapidly improving...

  • 9 Mind-Blowing Canvas Demos

    The <canvas> element has been a revelation for the visual experts among our ranks.  Canvas provides the means for incredible and efficient animations with the added bonus of no Flash; these developers can flash their awesome JavaScript skills instead.  Here are nine unbelievable canvas demos that...

Incredible Demos

  • spellcheck Attribute

    Many useful attributes have been provided to web developers recently:  download, placeholder, autofocus, and more.  One helpful older attribute is the spellcheck attribute which allows developers to  control an elements ability to be spell checked or subject to grammar checks.  Simple enough, right?

  • Simple Image Lazy Load and Fade

    One of the quickest and easiest website performance optimizations is decreasing image loading.  That means a variety of things, including minifying images with tools like ImageOptim and TinyPNG, using data URIs and sprites, and lazy loading images.  It's a bit jarring when you're lazy loading images and they just...

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!