Q承诺不起作用,减lessfunction

我试图返回最早修改date的目录中的文件。 这种方法似乎在createFileDateMap函数中失败。 我想减less一个文件path的数组,并创build一个文件名和MODdate的对象。 getModDate函数是一个asynchronous的fs.lstat调用。 我似乎无法设置我的reducer的acc从.then()块内的值。 当值取决于asynchronous调用时,我不确定如何实现减less

var _ = require('lodash'), fs = require('fs'), path = require('path'), Q = require('q'); function checkDir(dir) { // Check if given path is valid directory var deferred = Q.defer(); fs.lstat(dir, deferred.makeNodeResolver()); return deferred.promise.invoke('isDirectory'); } function getFiles(dir) { // Get all files within a directory var deferred = Q.defer(); fs.readdir(dir, deferred.makeNodeResolver()); return deferred.promise; } function makeFullPathFileArr(dir, files) { // Return array of full paths return _.map(files, function(file) { return path.join(dir, file); }); } function getModDate(file) { // Return modification date of file var deferred = Q.defer(); fs.stat(file, deferred.makeNodeResolver()); return deferred.promise.get('mtime'); } function createFileDateMap(filesArr) { // Return an obj of file paths and modification dates as Date objects // {{ file1: Date, file2: Date }} var fileDateMap = _.reduce(filesArr, function(acc, file) { getModDate(file) .then(function(modDate) { acc[file] = moment(modDate); }); return acc; }, {}); return fileDateMap; } function getMinDateFile(mapObj) { // return the file name which has the earliest modification date var dates = _.transform(mapObj, function(result, date, key) { result[key] = new Date(date); }); var minDate = new Date(Math.min.apply(null, _.values(dates))); var invertedMapObj = _.invert(mapObj); return invertedMapObj[minDate]; } var dir = '../reports'; checkDir(dir) .then(function(exist) { if(exist) { getFiles(dir) .then(function(fileNames) { return makeFullPathFileArr(dir, fileNames); }) .then(function(fullpathsArr) { return createFileDateMap(fullpathsArr); }) .then(function(fileAndDatesObj) { console.log(getMinDateFile(fileAndDatesObj)); }); } }) .catch(function(err) { console.log(err); }); 

感谢@BenjaminGruenbaum的帮助。 🙂

 function createFileDateMap(filesArr) { // Return an obj of file paths and modification dates as Date objects // {{ file1: Date, file2: Date return Q.all(_.map(filesArr, getModDate)) .then(function(modDates) { return _.zipObject(filesArr, modDates); }); } 

问题是reduce是同步的,不知道你在callback中使用的promise。 您将返回fileDateMap ,它是一个空对象。 有两个解决这个问题的方法:

  • 并行调用所有的getModDate ,使用Q.all来获得date数组的承诺,并在一个callback中减less该数量。

     function createFileDateMap(filesArr) { // Return an obj of file paths and modification dates as Date objects // {{ file1: Date, file2: Date }} return Q.all(_.map(filesArr, function(file) { return getModDate(file).then(function(date) { return {name:file, date:date}; }); })).then(function(fileAndDateArr) { return _.reduce(fileAndDateArr, function(acc, o) { acc[o.file] = moment(o.date); return acc; }, {}); }); } 
  • 使acc umlutor成为地图对象的承诺,并通过链接大量的调用来减less数组“asynchronous”。

     function createFileDateMap(filesArr) { // Return an obj of file paths and modification dates as Date objects // {{ file1: Date, file2: Date }} return _.reduce(filesArr, function(acc, file) { return acc.then(function(fileDateMap) { return getModDate(file).then(function(modDate) { fileDateMap[file] = moment(modDate); return fileDateMap; }); }); }, Q({})); }