2012-09-19 53 views
0

我有這樣的代碼爲什麼array.push不起作用?

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

的命運的陣列,但是當我在打印控制檯此happend

"img": [ 
    "/uploads/publish/alquiler/[email protected]", 
    "/uploads/publish/alquiler/[email protected]" 
], 

即時試圖得到這樣的結果

"img": [ 
    "/uploads/publish/alquiler/[email protected]", //first img 
    "/uploads/publish/alquiler/[email protected]"//second img 
], 

爲什麼.push()方法只放置第一個圖像目錄而不是第二個? 我想念什麼?

TNX

回答

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這樣的控制流庫可以簡化你的代碼,但是你需要開始思考,一旦你的函數進行了異步處理,它後面的所有內容都必須是異步的。

+0

我可以用fs.renameSync解決這個問題嗎? – andrescabana86

+0

tnx所有...我用renameSync()解決這個問題 – andrescabana86

2

ebohlman幾乎稱之爲它。現在您的for循環正在設置匿名函數,重命名函數完成後將調用它。

只要這些設置完成,imagenesIn將返回目錄。它可能包含一些目錄或不包含目錄,具體取決於在返回之前是否重命名完成。

節點的力量是它是異步的。你可以使用fs.renameSync yes,它會遵循你所期望的。節點不像一個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 in」遍歷對象的鍵。這對數組起作用,因爲它本質上是一個帶有數字鍵的對象。我能做到這一點然而

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

如果你沒有爲(VAR I = 0;我< array.length;我++),你就只能通過陣列的數據迭代。如果您用於(鍵入數組),您還可以遍歷nonNumericKey。這就是爲什麼我個人只對不是數組的對象使用「for in」。