import map from './map.js' import wrapAsync from './internal/wrapAsync.js' import awaitify from './internal/awaitify.js' /** * Sorts a list by the results of running each `coll` value through an async * `iteratee`. * * @name sortBy * @static * @memberOf module:Collections * @method * @category Collection * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over. * @param {AsyncFunction} iteratee - An async function to apply to each item in * `coll`. * The iteratee should complete with a value to use as the sort criteria as * its `result`. * Invoked with (item, callback). * @param {Function} callback - A callback which is called after all the * `iteratee` functions have finished, or an error occurs. Results is the items * from the original `coll` sorted by the values returned by the `iteratee` * calls. Invoked with (err, results). * @returns {Promise} a promise, if no callback passed * @example * * // bigfile.txt is a file that is 251100 bytes in size * // mediumfile.txt is a file that is 11000 bytes in size * // smallfile.txt is a file that is 121 bytes in size * * // asynchronous function that returns the file size in bytes * function getFileSizeInBytes(file, callback) { * fs.stat(file, function(err, stat) { * if (err) { * return callback(err); * } * callback(null, stat.size); * }); * } * * // Using callbacks * async.sortBy(['mediumfile.txt','smallfile.txt','bigfile.txt'], getFileSizeInBytes, * function(err, results) { * if (err) { * console.log(err); * } else { * console.log(results); * // results is now the original array of files sorted by * // file size (ascending by default), e.g. * // [ 'smallfile.txt', 'mediumfile.txt', 'bigfile.txt'] * } * } * ); * * // By modifying the callback parameter the * // sorting order can be influenced: * * // ascending order * async.sortBy(['mediumfile.txt','smallfile.txt','bigfile.txt'], function(file, callback) { * getFileSizeInBytes(file, function(getFileSizeErr, fileSize) { * if (getFileSizeErr) return callback(getFileSizeErr); * callback(null, fileSize); * }); * }, function(err, results) { * if (err) { * console.log(err); * } else { * console.log(results); * // results is now the original array of files sorted by * // file size (ascending by default), e.g. * // [ 'smallfile.txt', 'mediumfile.txt', 'bigfile.txt'] * } * } * ); * * // descending order * async.sortBy(['bigfile.txt','mediumfile.txt','smallfile.txt'], function(file, callback) { * getFileSizeInBytes(file, function(getFileSizeErr, fileSize) { * if (getFileSizeErr) { * return callback(getFileSizeErr); * } * callback(null, fileSize * -1); * }); * }, function(err, results) { * if (err) { * console.log(err); * } else { * console.log(results); * // results is now the original array of files sorted by * // file size (ascending by default), e.g. * // [ 'bigfile.txt', 'mediumfile.txt', 'smallfile.txt'] * } * } * ); * * // Error handling * async.sortBy(['mediumfile.txt','smallfile.txt','missingfile.txt'], getFileSizeInBytes, * function(err, results) { * if (err) { * console.log(err); * // [ Error: ENOENT: no such file or directory ] * } else { * console.log(results); * } * } * ); * * // Using Promises * async.sortBy(['mediumfile.txt','smallfile.txt','bigfile.txt'], getFileSizeInBytes) * .then( results => { * console.log(results); * // results is now the original array of files sorted by * // file size (ascending by default), e.g. * // [ 'smallfile.txt', 'mediumfile.txt', 'bigfile.txt'] * }).catch( err => { * console.log(err); * }); * * // Error handling * async.sortBy(['mediumfile.txt','smallfile.txt','missingfile.txt'], getFileSizeInBytes) * .then( results => { * console.log(results); * }).catch( err => { * console.log(err); * // [ Error: ENOENT: no such file or directory ] * }); * * // Using async/await * (async () => { * try { * let results = await async.sortBy(['bigfile.txt','mediumfile.txt','smallfile.txt'], getFileSizeInBytes); * console.log(results); * // results is now the original array of files sorted by * // file size (ascending by default), e.g. * // [ 'smallfile.txt', 'mediumfile.txt', 'bigfile.txt'] * } * catch (err) { * console.log(err); * } * })(); * * // Error handling * async () => { * try { * let results = await async.sortBy(['missingfile.txt','mediumfile.txt','smallfile.txt'], getFileSizeInBytes); * console.log(results); * } * catch (err) { * console.log(err); * // [ Error: ENOENT: no such file or directory ] * } * } * */ function sortBy (coll, iteratee, callback) { var _iteratee = wrapAsync(iteratee); return map(coll, (x, iterCb) => { _iteratee(x, (err, criteria) => { if (err) return iterCb(err); iterCb(err, {value: x, criteria}); }); }, (err, results) => { if (err) return callback(err); callback(null, results.sort(comparator).map(v => v.value)); }); function comparator(left, right) { var a = left.criteria, b = right.criteria; return a < b ? -1 : a > b ? 1 : 0; } } export default awaitify(sortBy, 3)