Asynchronous Grunt Tasks
Update: Thanks to @waynemoir for updating the example source to work with Grunt ~0.4.
After my last post @stevensacks tweeted at me that he was having issues getting node FileSystem commands to work in grunt. After a bit of poking around I noticed that there was no call to grunt’s async
method, which was probably preventing the process from finishing properly. So today’s post is a primer on async grunt processes, and how to make sure your node and grunt syntax is setup correctly.
Grab the Example Source
I’ve provided a simple grunt project at the link above. Take a look at the tasks
folder and you should see two custom tasks, grunt-read-write-local.js
and grunt-read-write-web.js
. The former will read a local file and write its contents to a new file. The latter will request a webpage and write its contents to a static file.
There are two asynchronous APIs at play here (Node’s and Grunt’s) and it’s important to understand both.
In Node an async operation will usually provide a callback, such is the case for fs.readFile, or it will use an event dispatch, for instance in an http request we listen for the data event.
Grunt, on the other hand, uses a token or a kind of promise. You grab a reference to grunt’s done
function and you wait till your node process has finished before calling it. If you take a look at grunt-read-write-local.js
you can see that we first call the async method to let grunt know it needs to wait:
and as we finish writing our file we tell grunt that everything completed succesfully and it’s ok to carry on:
We do something similar in our grunt-read-write-web
task but this time we work with Stream events.
The response returned by an http request implements the ReadableStream interface so it will emit data
and end
events. Node Streams have a great feature called pipes which handle the work of consuming data events and writing them to a destination. Sexy :) We still listen for the end
event coming from our request so we can notify grunt that the process has finished and it can move on.
Grab the Example Source
If you want to test it all out make sure you run npm install
first to pull down any dependencies. Then kick things off by running grunt
. I’m thinking my next post might be all about Streams in node since they’re such a cool concept. Thanks to @maxogden and @dominictarr for their great posts on the subject of streams.
Any questions or comments hit me up in the discussion area below.
You should follow me on Twitter here.