DEFINITION
File#createDirectoriesFromJSON (json, cb);
json: JSON object.
cb: Function. Parameters: error (Error), created (Boolean, true if at least one directory has been created).
Supose that the File class contains a property named _path that contains the path of a directory.
USAGE
var json = {
b: {
c: {
d: {},
e: {}
},
f: {}
},
g: {
h: {}
}
};
//this._path = "."
new File (".").createDirectoriesFromJSON (json, function (error, created){
console.log (created); //Prints: true
//callback binded to the File instance (to "this"). Hint: cb = cb.bind (this)
this.createDirectoriesFromJSON (json, function (error, created){
console.log (created); //Prints: false (no directory has been created)
});
});
RESULT
Under “.” the directory tree showed in the json object has been created.
./b/c/d
./b/c/e
./b/f
./b/g/h
IMPLEMENTATION
This is what I have without async.js:
File.prototype.createDirectoriesFromJSON = function (json, cb){
cb = cb.bind (this);
var created = false;
var exit = false;
var mkdir = function (path, currentJson, callback){
var keys = Object.keys (currentJson);
var len = keys.length;
var done = 0;
if (len === 0) return callback (null);
for (var i=0; i<len; i++){
(function (key, i){
var dir = PATH.join (path, key);
FS.mkdir (dir, function (mkdirError){
exit = len - 1 === i;
if (mkdirError && mkdirError.code !== "EEXIST"){
callback (mkdirError);
return;
}else if (!mkdirError){
created = true;
}
mkdir (dir, currentJson[key], function (error){
if (error) return callback (error);
done++;
if (done === len){
callback (null);
}
});
});
})(keys[i], i);
}
};
var errors = [];
mkdir (this._path, json, function (error){
if (error) errors.push (error);
if (exit){
errors = errors.length === 0 ? null : errors;
cb (errors, errors ? false : created);
}
});
};
Just for curiosity I want to rewrite the function using async.js. The problem here is that the function is recursive and parallel. For example, the “b” folder is created in parallel with “g”. The same for “b/c” and “b/f”, and “b/c/d” and “b/c/e”.
My attempt:
Tested with:
Notes:
errors.push(mkdirError);means that the directory couldn’t be created,return fn(null);could be appended to it to stop the directory creation from this branch.cbwill receive a third argument that will always benull..mkdirSyncRecursive()for this kind of task, or substack async mkdirp.[Update] Using mkdirp and lodash (or underscore) the code can be even clearer:
Tested with:
Note:
iteratorcould be removed by using partial function application, however underscore/lodash only support partial from left to right thus I did not wanted to require another library to do so.