for 循环引用出错的问题在 Nodejs 也存在?
for 循环引用出错的问题在 Nodejs 也存在?
想写一个递归创建目录的脚本, 开始发现创建目录都不对的… 先是一个模块:
events = require "events"
exports.ring = ring = new events.EventEmitter
create_file = (base_path, data) ->
if (typeof data) is "string"
file_path = path.join base_path, data
fs.writeFile file_path, ""
else
for key, value of data
new_path = path.join base_path, key
fs.mkdir new_path, ->
create_file new_path, value
ring.on "create", (tree, base_path) ->
base_path = base_path or "."
create_file base_path, tree
然后在另一个文件引用:
file_tree =
"parent": "child"
"tree":
"a": "aa"
"b": "bbb"
scaffold = require("../lib/index").ring
scaffold.emit "create", file_tree
创建的目录结构是这样的:
➤➤ tree
.
|-- create.coffee
|-- parent
`-- tree
|-- a
`-- b
`-- bbb
create.coffee
是我跑脚本的文件, 文件树几个子文件没有创建成功…
然后我把 for in
循环改成了 Object.keys
和 forEach
, 文件创建成功,
以前在 DOM 节点绑定操作的时候遇到过这个问题, 为什么文件操作里也有?
记得原来的说法是循环当中没有创建作用域, 可传值在 JS 里也出错的么?
new_path = path.join base_path, key
fs.mkdir new_path, ->
create_file new_path, value
为了让所有人看明白,转换成正常的javascript语法
new_path=path.join(base_path,key);
fs.mkdir(new_path,function(err){
create_file(new_path,value);
});
第二行的new_path确实是传值给fs.mkdir函数,但是第三行的new_path却不是在fs,mkdir的作用域内,而是在闭包回调函数的作用域内,它是指向第一行的new_path的。
模拟测试代码
var tree={a:'a',b:'b'};
var keys=Object.keys(tree);
for(var i=0;i<keys.length;i++){
var path='/root/'+keys[i];
create_path(path,function(err){
console.log('from callback - %s',path);
});
}
function create_path(path,callback){
process.nextTick(function(){
console.log('from function - %s',path);
callback();
});
}
这么说完全是异步的操作都会出这样的问题咯… 而且 DOM 和 fs 的操作全都是异步的, 这样的确好理解多了 那么以后对于这样的情况都应该用闭包处理一遍了 … 怎么会这样的… 不能传值
非不能,只是闭包函数没有明确定义接受值的参数,不怕麻烦可以bind一个参数进去,例如这样就能达到传值的目的。
var tree={a:'a',b:'b'};
var keys=Object.keys(tree);
for(var i=0;i<keys.length;i++){
var path='/root/'+keys[i];
create_path(path,function(path,err){
console.log('from callback - %s',path);
}.bind(undefined,path));
}
function create_path(path,callback){
process.nextTick(function(){
console.log('from function - %s',path);
callback();
});
}
原来这样也可以, 感觉和闭包类似啊
在Node.js中,for...in
循环确实可能引起一些问题,特别是在处理异步操作时。这是因为for...in
循环中的异步操作可能会在循环完成之前执行完毕,导致变量的值在循环内部和外部不一致。
下面是一个示例代码,展示了使用for...in
循环和使用Object.keys
和forEach
的区别:
使用 for...in
循环
const fs = require('fs');
const path = require('path');
const createFile = (basePath, data) => {
if (typeof data === 'string') {
const filePath = path.join(basePath, data);
fs.writeFile(filePath, "", (err) => {
if (err) console.error(err);
});
} else {
for (let key in data) {
const newPath = path.join(basePath, key);
fs.mkdir(newPath, () => {
createFile(newPath, data[key]);
});
}
}
};
createFile(".", {
"parent": "child",
"tree": {
"a": "aa",
"b": "bbb"
}
});
使用 Object.keys
和 forEach
const fs = require('fs');
const path = require('path');
const createFile = (basePath, data) => {
if (typeof data === 'string') {
const filePath = path.join(basePath, data);
fs.writeFile(filePath, "", (err) => {
if (err) console.error(err);
});
} else {
Object.keys(data).forEach(key => {
const newPath = path.join(basePath, key);
fs.mkdir(newPath, () => {
createFile(newPath, data[key]);
});
});
}
};
createFile(".", {
"parent": "child",
"tree": {
"a": "aa",
"b": "bbb"
}
});
在这两个例子中,第一个使用了for...in
循环,而第二个使用了Object.keys
和forEach
。后者避免了由于循环变量作用域带来的问题,并且能确保每个异步操作正确执行。
解释
for...in
循环:在异步操作(如fs.mkdir
)中使用for...in
循环时,循环变量可能会被覆盖,导致后续的操作无法正确执行。Object.keys
和forEach
:通过将对象的键转换为数组并使用forEach
遍历,可以确保每个异步操作都能独立执行,避免作用域问题。
总之,在处理异步操作时,建议使用Object.keys
和forEach
来代替for...in
循环,以避免潜在的作用域问题。