Improving Node.JS I/O Operations with ES8 Async/Await and Util.promisify()

If you’re running a node or express app, chances are you value asynchronous programming. You also probably know that all I/O operations are taxing on your app. If not, you should maybe look into that and how not to block the Node.js event loop. I recommend reading: https://nodejs.org/en/docs/guides/dont-block-the-event-loop/
To be short, sweet and to the point here are some ways I have promisified my filesystem (hint: i/o) calls and other packages that otherwise follow the error-first callback function style. such as:
fs.writeFile(file, data, (err) => {} );
Option 1) Javascript Promise API Wrapper
The following is an example of the use of a Javascript Promise api wrapper, snuck into an async/await (but lacking a try/catch). Could this be written better? probably.. I welcome your feedback! Does it work? yes.. it works ridiculously well and has scaled in Node solutions for me that fetch, parse, transform and bulk insert data in amounts exceeding 6 million JSON files/day on some pretty nifty, very Async, Express API Microservices that I built.
const fs = require(fs);const readDirectory = async(path) => {
return await new Promise( (resolve, reject) => {
fs.readdir(dir, async(err, data) => {
err ? reject(err) : resolve(data);
});
});
}
Option 2) use of Node.js ≥ 8.0 util.promisify = async heaven.
This is an example of a solution that will help you save json into recursive folders and also build those recursive folders if they don’t yet exist. This will show you how easy it is to promisify a 3rd party module like the awesome mkdirp package or to reach under node’s hood and promisify it’s included fs module, which will help with many of the basic filesystem operations your Node app may need to perform. In my case I save and read JSON files extracted from API’s.
// require the packages you want
const mkdirp = require('mkdirp');
const fs = require('fs');
const { promisify } = require('util');//declare your needed method as a variable
const readFileAsync = promisify(fs.readdir); //<-- nodejs module
const mkDirpAsync = promisify(mkdirp); //<-- 3rd party npm package/* call them in order with an awesome es8 async/await function. in es8 async/await we rely on a try/catch to resolve/reject our code.*/ const makeRecursiveFileAsync = async(data) => {
try{
let json = JSON.stringify(data);
let dir = `recursive/folders/I/wanted/in/my/fs`;
let name = `somefilename.json`;
let path = `${dir}/${name}`; let makeDirpAsync = await mkDirpAsync(dir);
let makeFileAsync = await writeFileAsync(path, json);
return path;
}
catch(err){
return Object.assign(err);
}
}
Note: To make this work for you you would need a json object in memory somewhere (I use and also promisify the fs.readFile() for example and make use of JSON.parse() then simply pass it into the above es8 function, such as the following:
fetch('someurlendpoint')
.then( res => makeRecursiveFileAsync( JSON.parse(res.data) ); )
I will attempt to improve this post soon. But I had to get the initial excite out. :) enjoy! let me know what you were able to promisify! If you need some help, here is the official Node.js documentation. Good luck! https://nodejs.org/dist/latest-v8.x/docs/api/util.html#util_util_promisify_original