我目前正在练习使用电子的过程,但是我对javascript很陌生,遇到了一个让我完全困惑的问题。我有以下代码:
function getPaths() {
var dirPath = document.getElementById("mdir").innerHTML;
var filePaths = [];
fs.readdir(dirPath, function(err, dir) {
for(var i = 0, l = dir.length; i < l; i++) {
var filePath = dir[i];
filePaths.push(dirPath + "/" + filePath);
}
});
console.log(filePaths);
console.log(filePaths.length);
}
应该查看由定义的目录dirPath
,然后循环遍历并获取该目录中所有文件的完整路径。它将它们附加到数组,然后在底部,将数组记录到控制台,然后是数组的长度。令我感到困惑的是,给定该代码,该阵列将日志记录到控制台,如预期的那样,但是控制台记录的长度为零。我目前的想法是,它与范围有关,但这没有任何意义,因为我是filePaths
在正在运行的函数上方的函数中声明数组。除非我错过任何事情。谁能指出我做错了什么?
readdir
是异步的。它不会立即得到结果。你应该记录filePaths
内部回调。控制台显示该值的唯一原因是因为控制台在展开数组时会评估该数组。
当你按下左侧的小箭头时,将鼠标放在i
右侧的框中。发生的情况是,控制台保留了对该数组的引用,因此,当用户展开该数组时,它将显示其当前值。但是,当你记录filePaths.length
数组为空时,因为readdir
尚未完成读取,因此这就是为什么你得到0。但是当你打开控制台并按该箭头时,readdir
将已经完成读取,并且控制台将打印数组的当前值(填充后)。
演示该问题的示例:(不是解决方案,只是为了了解实际情况)
尝试运行以下代码,看看会发生什么:
var arr = [];
setTimeout(function() {
arr.push(1, 2, 3);
}, 5000);
console.log(arr.length);
console.log(arr);
在这里,数组及其长度都在数组被填充之前被记录下来。5秒钟后将填充阵列。因此输出将为0
和字符串array[]
。现在,由于数组可能包含大量数据,因此在用户展开数组之前,控制台不会显示该数据。因此,控制台要做的就是保留对阵列的引用,直到用户按下展开箭头。如果在5秒钟前展开阵列,你会看到阵列为空(尚未填充)。如果你等到5秒钟过去,然后将其展开,那么你会发现它已经装满了。
注意:此外,登录到控制台的行(类似> Array(0)
)只是发生日志时对象/数组的字符串表示形式。如果对象/数组发生更改,则不会更新。因此有时似乎也令人困惑。
我希望现在很清楚。
我不建议使用
setTimeout
功能,因为响应时间可能会因目录内容而异我没有建议使用@MaxZoom
setTimeout
作为解决方案!我只是使用一个易于理解的示例来解释OP的问题,该示例setTimeout
用来强调问题的异步性!好的,所以如果我做对了,之所以没有得到值,是因为readdir是异步的。结果,console.log()在构建数组之前完成,结果返回0?
完全是@Taira!
readdir
会在读取完成后重新调用要调用的回调,然后继续执行下一条语句并执行它(与发生的事情几乎相同setTimeout)
)!如果要使用同步版本readdirSync
(但我不推荐)。好的,那很有道理!我来自Python背景,所以这种事情对我来说很陌生。但是还有一个问题:出于好奇,为什么
readdirSync
不推荐?