This is a simple example using Promises in a reduce call to execute mkdir commands in sequence.

I'm using the util.promisify utility to automatically convert the standard fs functions into Promises.

Because the last Promise resolved in the reduce is passed the full path to make, this function also returns the full path created.

const fs = require('fs');
const util = require('util');
const path = require('path');

const fsReaddir = util.promisify(fs.readdir);
const fsExists = util.promisify(fs.exists);
const fsMkdir = util.promisify(fs.mkdir);
const fsStat = util.promisify(fs.stat);

function recursiveMkdir(dir) {
    const paths = dir.split(path.sep);

    if (paths[0] == '') {
        paths[0] = path.sep;
    } else if (paths[0].indexOf(':') > 0) {
        paths[0] = paths[0] + path.sep;
    }

    return paths.reduce((p, n) => {
        return p.then((baseDir) => {
            const pathToMk = path.join(baseDir, n);
            return fsExists(pathToMk).then((e) => {
                if (!e) {
                    // path doesn't exist, make it
                    return fsMkdir(pathToMk).then(() => {
                        return pathToMk;
                    });
                } else {
                    // path already exists, check it's a directory
                    return fsStat(pathToMk).then((stats) => {
                        if (!stats.isDirectory()) {
                            return Promise.reject(new Error(`Unable to create path ${pathToMk}, not a directory`));
                        }
                        return pathToMk;
                    })
                }
            });
        });
    }, Promise.resolve(''));
}

recursiveMkdir(path.join(__dirname, 'testdir'));