为什么array.push不起作用?

时间:2012-09-19 08:36:47

标签: javascript node.js express

我有这个代码

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

2 个答案:

答案 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)

ebohlman几乎称之为。现在你的for循环正在设置重命名函数一旦完成就会调用的匿名函数。

一旦设置完成,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。这就是为什么个人,我只使用"进入"对于不是数组的对象。