Javascript that uses callbacks, is hard to get right intuitively. A lot of code ends up looking like this:
fs.readdir(source, function(err, files) {
if (err) {
console.log('Error finding files: ' + err)
} else {
files.forEach(function(filename, fileIndex) {
console.log(filename)
gm(source + filename).size(function(err, values) {
if (err) {
console.log('Error identifying file size: ' + err)
} else {
console.log(filename + ' : ' + values)
aspect = (values.width / values.height)
widths.forEach(function(width, widthIndex) {
height = Math.round(width / aspect)
console.log('resizing ' + filename + 'to ' + height + 'x' + height)
this.resize(width, height).write(
destination + 'w' + width + '_' + filename, function(err) {
if (err) console.log('Error writing file: ' + err)
}
)
}.bind(this))
}
})
})
}
})
A Promise is used for deferred and asynchronous computations. A Promise represents an operation that hasn't completed yet, but is expected in the future.
// You should use promises to turn this:
fs.readFile("file.json", function (err, val) {
if (err) {
console.error("unable to read file");
}
else {
try {
val = JSON.parse(val);
console.log(val.success);
}
catch (e) {
console.error("invalid json in file");
}
}
});
// Into this:
fs.readFileAsync("file.json").then(JSON.parse).then(function (val) {
console.log(val.success);
})
.catch(SyntaxError, function (e) {
console.error("invalid json in file");
})
.catch(function (e) {
console.error("unable to read file");
});
As the Promise.prototype.then() and
Promise.prototype.catch() methods return
promises, they can be chained
// We use new Promise to construct the promise.
// We give the constructor a factory function
// which does the actual work.
function readFile(filename, enc){
return new Promise(function (resolve, reject){
fs.readFile(filename, enc, function (err, data){
if (err) reject(err);
else resolve(data);
});
});
}
The passed in function will receive functions resolve and reject as its arguments which can be called to seal the fate of the created promise.