我有这个代码
function imagenesIn(errU,errores)
{
if(errU) throw errU;
var directorios=new Array();
var origenDir='';
var destinoDir='';
if(errores=='')
{
if(campos.img instanceof Array)
{
for(file in campos.img)
{
origenDir='';
destinoDir='';
origenDir=campos.img[file].path;
destinoDir='/uploads/publish/alquiler/'+req.session.passport.user+campos.img[file].name;
fs.rename(origenDir,process.cwd()+'/public'+destinoDir,function(err)
{
if (err) throw err;
directorios.push(destinoDir);
console.dir(directorios)
})
}
}
}else{
res.send(errores)
}
return directorios;
},
我想让directorios获得req.files.img中所有文件内容命运的数组 在campos.img
但是当我在控制台中打印时会发生这种情况
"img": [
"/uploads/publish/alquiler/andres@hotmail.comTulips.jpg",
"/uploads/publish/alquiler/andres@hotmail.comTulips.jpg"
],
我试图得到这个结果
"img": [
"/uploads/publish/alquiler/andres@hotmail.comTulips.jpg", //first img
"/uploads/publish/alquiler/andres@hotmail.flowers.jpg"//second img
],
为什么.push()方法只放第一个图像目录而不是第二个??? 我错过了什么?
TNX
答案 0 :(得分:3)
你的问题在于
fs.rename(origenDir,process.cwd()+'/public'+destinoDir,function(err)
{
if (err) throw err;
directorios.push(destinoDir);
console.dir(directorios)
})
你的push()
在你做的时候实际上不会运行
return directorios;
您需要确保最后 的fs.rename(...)
的调用(不,我重复不,必须与启动最后一次的呼叫相同)处理所有呼叫都已完成的情况。使用异步调用,不能在启动它们之后才能完成并执行return
;在完成所有工作之后,你必须把你想要运行的代码放在一个回调中,该回调解决了我之前称之为“句柄”的问题。
像async.js这样的控制流程库可以简化你的代码,但是你需要了解一下,一旦你的函数变为异步,它后面的所有内容都必须是异步的。
答案 1 :(得分:2)
一旦设置完成,imagenesIn将返回目录。它可能包含部分目录,也可能不包含任何目录,具体取决于在返回之前是否完成重命名。
节点的力量是它是异步的。您可以使用fs.renameSync yes,它会遵循您的期望。 Node不像apache php服务器。 php服务器获取请求,并为请求保留一小部分内存。这就是为什么其他请求仍然可以处理的原因,因为它们都有自己的记忆。 Node并没有这样做。它运行在一个线程上,如果你做任何阻塞的事情(比如同步IO),其他请求必须等到它完成才能被处理。
理想情况下,您的imagenesIn也应该是异步的,将函数作为最终参数。函数的标准通常遵循函数(错误,数据)。如果没有,则错误应为null。 fs.rename遵循这种模式。
调用imagenesIn的函数也应理想地处理服务器响应。这允许该功能用于其他类型的情况。如果您不想在错误时发送特定回复,该怎么办?如果您不想发送回复怎么办?现在,这是一个不小心发送标题两次(并收到错误)的好方法。
如果是我,这就是我写你的功能的方式(我没有测试,但应该给你一些方向)。
function imagenesIn(callback) {
var directorios=new Array();
var origenDir='';
var destinoDir='';
if(campos.img instanceof Array) {
function recursion(index){
//the case that ends the recursion and returns directories
if (index >= campos.img.length) {
callback(null, directorios);
return;
}
origenDir=campos.img[index].path;
destinoDir='/uploads/publish/alquiler/'+req.session.passport.user+campos.img[index].name;
fs.rename(origenDir, process.cwd() + '/public' + destinoDir, function(err) {
//the case that ends recursion and sends an error
if (err) {
callback(err);
return;
}
directorios.push(destinoDir);
console.dir(directorios);
recursion(index++);
})
}
recursion(0);
}
else {
callback('Campos.img was not an array.');
}
}
并且调用它的代码可能看起来像这样
imagenesIn(function(err, directories) {
if (err) {
res.send(err);
}
else {
//do cool stuff with directories.
}
});
另外,我想确保你理解for(;;)和for(key in object)之间的独特区别。 "对于"迭代对象的键。这适用于数组,因为它本质上是一个带有数字键的对象。我可以做到这一点
var array = ['data', 'data'];
array.nonNumericKey = 'otherdata';
如果你这样做(var i = 0; i< array.length; i ++),你只会遍历数组数据。如果您使用(键入数组),您还将遍历nonNumericKey。这就是为什么个人,我只使用"进入"对于不是数组的对象。