Nodejs在使用Loop下载许多文件时丢失了数据
Nodejs lost data when using Loop for download many files
今天,我试图从我的服务器下载许多文件
下载.js
function getPhotos(req, res) {
//Get User Photos
var fileReader = fs.readFile('./../data/user.json', 'utf8', function(err, data) {
if (err)
console.log(err);
else {
var dataJson = JSON.parse(data);
//console.log(dataJson.Person);
for (var i = 0; i < dataJson.Person.length; i++) {
var options = {
host : '10.16.47.128', // Local Server IPAddress
port : 2013, //Port
path : '/ExternalServer/avatar/' + dataJson.Person[i].Username + '.jpg',
};
//console.log(dataJson.Person[i].Username);
var fileAvatarPhotos = fs.createWriteStream('./../avatar/' + dataJson.Person[i].Username + '.jpg');
fs.exists(fileAvatarPhotos, function(exists) {//Check Exist File
if (exists) {
var req = http.get(options, function(res) {
//console.log(res);
res.pipe(fileAvatarPhotos);
});
} else {
var req = http.get(options, function(res) {
fs.writeFile(fileAvatarPhotos, '', function(err) {
if (err)
return console.log(err);
var req = http.get(options, function(res) {
//console.log(res);
res.pipe(fileAvatarPhotos);
});
});
});
}
});
}
}
});
//End Get User Photos
}
当我运行代码时:
node download.js
系统下载了所有照片,但照片大小为0kb。并且有错误:
stream.js:81投掷者;//管道中出现未处理的流错误。^错误:OK,关闭
此外,当我抛出循环时(例如:修复dataJson.Person[I].Username,将I更改为10)
运行代码后,系统重新生成正确的照片。
发生了什么?如何修复?
致以最崇高的敬意。!
在for循环中实现这样的功能不是一个好主意。这是因为在循环中有异步操作,但循环的每一次迭代都会立即执行。在您的案例中,您正在定义fileAvatarPhotos,它是一个WriteStream对象。http.get方法是异步的,因此在其回调中,您可以使用为循环的第三次迭代、第四次迭代或第一次迭代定义的fileAvatarPhotos。这取决于情况。你可以尝试将你的代码转换成这样的东西:
var files = ["file1.jpg", "file2.jpg", "file3.jpg"];
var readFile = function(callback) {
if(files.length > 0) {
var file = files.shift();
http.get({path: file}, function(res) {
// ... process the result
readFile(callback);
})
} else {
callback();
}
}
readFile(function() {
console.log("reading finishes");
});
即,一次又一次地调用readFile,直到files数组中不再有元素为止。
Javascript没有循环块作用域,它有基于函数的作用域。
这意味着,正如Krasimir所指出的,for循环变量正在相互覆盖在它们被使用完之前。
所以,你至少需要把for循环的内部结构包裹在一个函数中,或者看起来奇怪的事情就会开始发生。
即使这种情况得到了解决,代码也会尝试同时进行所有下载,而Krasimir的答案可能更清晰,因为他避免了这种情况。
尽管如此,使用一个函数来确保每个for循环执行都有自己的作用域是知道这件事是件好事。
循环修改如下:
for (var i = 0; i < dataJson.Person.length; i++) {
(function(i){
var options = {
host : '10.16.47.128', // Local Server IPAddress
port : 2013, //Port
path : '/ExternalServer/avatar/' + dataJson.Person[i].Username + '.jpg',
};
//console.log(dataJson.Person[i].Username);
var fileAvatarPhotos = fs.createWriteStream('./../avatar/' + dataJson.Person[i].Username + '.jpg');
fs.exists(fileAvatarPhotos, function(exists) {//Check Exist File
if (exists) {
var req = http.get(options, function(res) {
//console.log(res);
res.pipe(fileAvatarPhotos);
});
} else {
var req = http.get(options, function(res) {
fs.writeFile(fileAvatarPhotos, '', function(err) {
if (err)
return console.log(err);
var req = http.get(options, function(res) {
//console.log(res);
res.pipe(fileAvatarPhotos);
}); // http.get
}); // fs.writeFile
}); // http.get
} // else
}); // fs.exists
})(i); // anonymous function to create scopes for loop
} //for loop
相关文章:
- 如何使用.log数据文件显示EXT-js网格
- 如何在javascript中使用会话特定的数据文件
- 数据文件出现 D3 错误
- HTML 对象数据文件(如果未找到)
- 在 JSFiddle 中链接外部 JSON 数据文件
- 如何从 SDK 插件数据文件夹加载 DLL
- 使用 jquery 从 json 数据文件动态填充选择元素
- 节点模块包括数据文件作为全局变量
- 如何获取 HTML 标记的“数据文件”属性的内容
- 在 d3.js 散点文件中使用数据数组而不是外部数据文件
- 我用PHP调用的数据文件神秘地被更改了.用户是否覆盖了它
- 从数据文件导入数组
- 谷歌驱动器API应用程序数据文件夹,是真的那么困难
- XML数据文件已更改,但更改不会;t出现在gmaps中的html页面上
- 大文件(超过~2Mb)上传-引发错误“;键'数据文件'在<MultiValueDict:{}>
- 将数据文件转换为blob
- 如何使用链接检索整个数据文件(ajax?)
- firefox(9),javascript,由于大数据文件导致分配大小溢出.有什么办法可以避免这种情况吗
- 我们可以在json数据文件中添加图像,并使用D3.js在页面上调用它
- IANA (Internet Assigned Numbers Authority)数据文件和来自www.timeand