我正在尝试将文件返回到最早修改日期的目录中。这种方法似乎在createFileDateMap函数中失败了。我想减少一个文件路径数组,并创建一个文件名和模态日期的对象。 getModDate函数是一个异步fs.lstat调用。我似乎无法将我的reducer的acc设置为.then()块中的值。当值依赖于异步调用
时,我不确定如何实现减少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);
});
答案 0 :(得分:3)
感谢@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);
});
}
答案 1 :(得分:0)
问题是reduce
是同步的,并且不知道您在其回调中使用的promise。您将返回fileDateMap
,这是一个空对象。这个问题有两种解决方案:
并行调用所有getModDate
,使用Q.all
获取日期数组的承诺,并在then
回调中减少该承诺。
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成为地图对象的承诺,并通过链接大量then
次呼叫来减少“异步”数组。
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({}));
}