0

我有这个代码

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;
    },

我想在directios中获取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

4

2 回答 2

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 这样的控制流库可以简化你的代码,但是你需要明白一旦你的函数变成异步的,它后面的所有东西也必须是异步的。

于 2012-09-19T08:52:49.663 回答
2

ebohlman 几乎称它为。现在,您的 for 循环正在设置 rename 函数完成后将调用的匿名函数。

一旦这些设置完成,imagenesIn 将返回目录。它可能包含一些目录,也可能不包含目录,具体取决于您返回之前是否完成了重命名。

节点的强大之处在于它是异步的。您可以使用 fs.renameSync 是的,它会按照您的预期进行。Node 不像 apache php 服务器。php 服务器收到一个请求,并为该请求保留一小块内存。这就是为什么仍然可以处理其他请求的原因,因为它们都有自己的内存。节点不这样做。它在单个线程上运行,如果您执行任何阻塞操作(如同步 IO),其他请求必须等到它完成才能处理它们。

理想情况下,您的 imagenesIn 也应该是异步的,将函数作为最终参数。函数的标准通常遵循函数(错误,数据)。如果没有,则错误应该为空。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) 之间的独特区别。“For in”遍历对象的键。这适用于数组,因为它本质上是一个带有数字键的对象。不过我可以这样做

var array = ['data', 'data'];
array.nonNumericKey = 'otherdata';

如果你为 (var i = 0; i < array.length; i++) 做了,你只会遍历数组数据。如果您使用 for (key in array),您还将遍历 nonNumericKey。这就是为什么我个人只对不是数组的对象使用“for in”。

于 2012-09-20T04:43:35.793 回答