what could possibly go wrong?
Call backs are not the enemy.
readFile('test.txt', function(err, contents) {
if(err) {
return console.error(err);
}
console.log(contents);
});
var filteredList = userList.filter(function(user){
return user.selected === true;
});// 88
vs.
let filteredList = userList.filter({selected} => selected === true);// 69 | 21.59% reduction.
Passing functions as an argument is a beautiful thing.
var fs = require('fs')
var path = require('path')
module.exports = function (dir, cb) {
fs.readdir(dir, function (er, files) { // [1]
if (er) return cb(er)
var counter = files.length;
var errored = false;
var stats = [];
files.forEach(function (file, index) {
fs.stat(path.join(dir,file), function (er, stat) { // [2]
if (errored) return;
if (er) {
errored = true;
return cb(er);
}
stats[index] = stat; // [3]
if (--counter == 0) { // [4]
var largest = stats
.filter(function (stat) { return stat.isFile(); }) // [5]
.reduce(function (prev, next) { // [6]
if (prev.size > next.size) return prev;
return next;
});
cb(null, files[stats.indexOf(largest)]); // [7]
}
});
});
});
};
Read all the files inside the directory.
Gets the stats on each file. A counter is used to track when all I/O has finished. Errored boolean prevents the provided callback from being called more than once if an error occures.
Collect the stats for each file.
Check to see if all parallel operations have completed
Only grab regular files.
Reduce the list to the largest file.
Pull the file name associated with the state and callback.
var fs = require('fs')
var async = require('async')
var path = require('path')
module.exports = function (dir, cb) {
async.waterfall([ // [1]
function (next) {
fs.readdir(dir, next)
},
function (files, next) {
var paths =
files.map(function (file) { return path.join(dir,file) })
async.map(paths, fs.stat, function (er, stats) { // [2]
next(er, files, stats)
})
},
function (files, stats, next) {
var largest = stats
.filter(function (stat) { return stat.isFile() })
.reduce(function (prev, next) {
if (prev.size > next.size) return prev
return next
})
next(null, files[stats.indexOf(largest)])
}
], cb) // [3]
}
Pro's
Con's
The then() method returns a promise. It takes two arguments: callback functions for the success and failure cases of the Promise.
p.then(onFulfilled, onRejected);
p.then(function(value) {
// fulfillment
}, function(reason) {
// rejection
});
var p1 = new Promise(function(resolve, reject) {
resolve("Success!");
});
p1.then(function(value) {
console.log(value); // Success!
});
The catch() method returns a Promise and deals with rejected cases only. It behaves the same as calling:
Promise.prototype.then(undefined, onRejected)
var p1 = new Promise(function(resolve, reject) {
reject("This is why we can't have nice things!");
});
p1.catch(function(error) {
console.log(error); // This is why we can't have nice things!
});
The Promise.all(iterable) method returns a promise that resolves when all of the promises in the iterable argument have resolved, or rejects with the reason of the first rejected promise.
var p1 = Promise.resolve(3);
var p2 = 1337;
var p3 = new Promise(function(resolve, reject) {
setTimeout(resolve, 100, "foo");
});
Promise.all([p1, p2, p3]).then(function(values) {
console.log(values); // [3, 1337, "foo"]
});
Correspondence between synchronous and asynchronous functions
getTweetsFor("domenic") // promise-returning async function
.then(function (tweets) {
// promise-returning async function
return expandUrlUsingTwitterApi(parseTweetsForUrls(tweets)[0]);
})
.then(doHttpRequest) // promise-returning async function
.then(function (responseBody) {
console.log("Most recent link text:", responseBody);
}).catch(function(error) {
console.error("Error with the twitterverse:", error);
});
try {
var tweets = getTweetsFor("domenic"); // blocking
// blocking x 2
var responseBody = doHttpRequest(expandUrlUsingTwitterApi(parseTweetsForUrls(tweets)[0]));
console.log("Most recent link text:", responseBody);
} catch (error) {
console.error("Error with the twitterverse: ", error);
}
var fs = require('fs');
var path = require('path');
var Promise = require('bluebird');
var fs_readdir = Promise.promisify(fs.readdir); // [1]
var fs_stat = Promise.promisify(fs.stat);
module.exports = function (dir) {
return fs_readdir(dir)
.then(function (files) {
var promises = files.map(function (file) {
return fs_stat(path.join(dir,file));
})
return Promise.all(promises).then(function (stats) { // [2]
return [files, stats]; // [3]
})
})
.then(function (data) { // [4]
var files = data[0];
var stats = data[1];
var largest = stats
.filter(function (stat) { return stat.isFile() })
.reduce(function (prev, next) {
if (prev.size > next.size) return prev;
return next;
})
return files[stats.indexOf(largest)];
})
} //830
const fs = require('fs');
const path = require('path');
const Promise = require('bluebird');
const fs_readdir = Promise.promisify(fs.readdir);
const fs_stat = Promise.promisify(fs.stat);
const getFileStats = filesList => filesList.map(file => fs_stat(path.join(dir,file)));
const findLargestFile = statsList =>
statsList
.filter(stat => stat.isFile())
.reduce((prev, next) => prev.size > next.size ? prev: next);
module.exports = dir =>
fs_readdir(dir).then(filesList =>
Promise.all(getFileStats(filesList)).then(statsList => [filesList, statsList]))
.then([filesList, statsList] => filesList[stats.indexOf(findLargestFile(statsList))]);
// 657 | 24.91% reduction
Pros:
Cons: