Node.js:回调变量作用域的问题
Node.js: problem with variable scope in callback
var result = { controllers: [], views: [], models: [] };
var dirs = ['controllers', 'views', 'models'];
dirs.forEach(function(dirname) {
fs.readdir('./' + dirname, function(err, res) {
if (err) throw err;
result[dirname] = res;
// #2
});
});
// #1
在这段代码中,让console.log(result);
运行在#1(见上文),空的控制器、视图和模型数组将被初始化记录。但是,我需要循环用通过fs
读取的相应文件名填充数组。
#2的console.log(result);
将在第三次迭代后记录填充所需值的result
对象。
我相信这与Node.js/JavaScript回调的异步特性有关。如果我不理解JavaScript变量作用域和异步方法是如何工作的,请原谅我,我都是新手。
这样做:
var result = { controllers: [], views: [], models: [] };
var dirs = ['controllers', 'views', 'models'];
var pending = 0;
dirs.forEach(function(dirname) {
pending++;
fs.readdir('./' + dirname, function(err, res) {
pending--;
if (err) throw err;
result[dirname] = res;
if (pending===0) goOn();
});
});
function goOn() {
// #1
}
我相信这与的异步特性有关Node.js/JavaScript回调。
是的,这可能就是为什么当您尝试在#1处输出result
变量的内容时,它是空的原因。在#1运行的时候,数据还没有被获取,因为在#2执行readdir
的回调时发生了"获取"动作。为了更好地了解回调和异步编程的工作原理,我建议您查看本文中所述的一些关于异步范式的参考资料。
对于那些对措辞感到困惑的人来说,下面是一个示例的输出,每个目录中都有一个'1'文件:
~/Documents/$ node test.js
{ controllers: [], views: [], models: [] } 1
{ controllers: [], views: [ '1' ], models: [] } 2
{ controllers: [ '1' ], views: [ '1' ], models: [] } 2
{ controllers: [ '1' ],
views: [ '1' ],
models: [ '1' ] } 2
这是因为进入文件系统需要异步操作。因此,由于Node不阻塞,之后的值将与异步操作完成之前的值相同。
它确实与回调有关。在
fs.readdir('./' + dirname, function(err, res) {
if (err) throw err;
result[dirname] = res;
// #2
});
传入的函数是一个回调函数,当目录被完全读取时执行。由于它是异步的,fs.readdir()在函数实际执行之前返回。
所以基本上,在forEach完成之后,有3个函数等待作为回调函数执行(每个目录一个)。代码在继续执行之前不会等待回调发生,因此如果在读取目录之前到达#1,它将在回调执行之前记录结果对象并对其进行适当修改。
可以使用fs。readdirSync,但只有当它不会对你的应用程序不好,如果这段代码短暂阻塞/没有危险,这段代码无限期阻塞和拖延你的程序。如果您需要它保持异步,请查看jh的答案。
我认为这与dirname在第一个函数返回后改变的值有关。要解决这个问题,只需将dirname复制到第二个函数调用的作用域中;
dirs.forEach(function(dirn) {
var dirname = dirn; // make a copy here
fs.readdir('./' + dirname, function(err, res) {
if (err) throw err;
result[dirname] = res;
// #2
});
});
- 作用域问题-此函数是否形成闭包-JavaScript
- 访问Javascript对象-Node.js的作用域问题
- 尝试将变量传递到对象中时的作用域问题'的方法构造函数
- 'simple'套接字中的作用域问题.IO服务器
- Javascript作用域问题,对象在分配后没有数据
- 可能存在Javascript作用域问题
- 本地Javascript作用域问题
- 设置Javascript函数的作用域问题
- Javascript 中使用 setTimeout 的作用域问题
- 作用域问题反应父子方法ES6
- jquery get中的作用域问题
- 绑定时出现Javascript作用域问题
- 试图覆盖全局变量时出现jQuery.post()作用域问题
- 作用域问题Uncaught ReferenceError
- 使用reduce串行链接Javascript承诺时的作用域问题
- Javascript变量作用域问题-错误:类型错误:this.graphics未定义
- extjs 4中的作用域问题
- 变量未正确赋值,可能存在作用域问题(getJSON()中的each()中有一个开关的函数)
- Javascript作用域问题:函数在$(doc).ready()中可用,但在事件处理程序中不可用
- Angular 2服务单例作用域问题