不能使用异步回调与.filter()
。 .filter()
需要同步结果,并且无法从异步操作中获取同步结果。所以,如果你打算使用异步fs.stat()
,那么你必须使整个操作异步。
下面介绍一种方法。请注意,即使randomFile()
需要异步传回其结果。我们在这里使用回调。
const path = require('path');
const fs = require('fs');
exports.randomFile = function(dir, callback) {
fs.readdir(dir, (err, files) => {
if (err) return callback(err);
function checkRandom() {
if (!files.length) {
// callback with an empty string to indicate there are no files
return callback(null, "");
}
const randomIndex = Math.floor(Math.random() * files.length);
const file = files[randomIndex];
fs.stat(path.join(dir, file), (err, stats) => {
if (err) return callback(err);
if (stats.isFile()) {
return callback(null, file);
}
// remove this file from the array
files.splice(randomIndex, 1);
// try another random one
checkRandom();
});
}
checkRandom();
});
}
而且,下面介绍如何使用另一个模块的异步接口。
// usage from another module:
var rf = require('./randomFile');
fs.randomFile('/temp/myapp', function(err, filename) {
if (err) {
console.log(err);
} else if (!filename) {
console.log("no files in /temp/myapp");
} else {
console.log("random filename is " + filename);
}
});
感谢这个脚本,它看起来像是'生产就绪'! :-)可能需要添加一个'path.join(dir,file)',以便'fs.stat'工作。 – jfix
@jfix - 好点,我补充说。 – jfriend00
@jfix - 当需要第二个参数(回调)时,您无法在第一个参数上有用地使用ES6默认值。你可以这样声明,但触发默认值的唯一方法是将“undefined”作为第一个参数传递,这很难讲出来。所以,我不认为'dir'的ES6默认参数在这种情况下是有意义的。它可以以旧式的方式实现,代码检查是否传递了一个或两个参数,如果只传递一个参数,则分配默认的'dir'。但是,我不知道如何让ES6为你做到这一点。 – jfriend00