2017-07-01 50 views
0

問題:物品推入對象數組

我想通過一個多上傳每個上傳的文件寫入fileinformation到我的數據庫來跟蹤我上傳的文件。但是,當我上傳2個文件時,通常會在數據庫中創建3個條目,而當我上傳6個文件時,它會創建6個以上的條目。

我的數據庫功能:

function saveAssetInDatabase(project, fileInformation) { 
    return new Promise((reject, resolve) => { 
     let uploaded_file = {} 
     uploaded_file = fileInformation 
     uploaded_file.file_type = 'asset' 
     uploaded_file.display_name = fileInformation.originalname 
     project.uploaded_files.push(uploaded_file) 
     project.save() 
    }) 
} 

其調用該函數的簡化代碼:

for(var i=0; i<req.files["sourceStrings"].length; i++) { 
    // Unknown file format, let's save it as asset 
    saveAssetInDatabase(project, fileInformation).then(result => { 
     return res.status(200).send() 
    }).catch(err => { 
     logger.error(err) 
     return res.status(500).send() 
    }) 
} 

我想這有什麼錯我的數據庫功能,因爲它會導致複製文件條目。我在這裏做錯了什麼?一個文件應該得到一個條目。

+1

使用'req.files.sourceStrings'的一點是什麼?作爲循環條件,但不在循環內部使用它?您現在總是保存相同的資產 – nem035

+0

請確保您的req.files ['sourseStrings']沒有dublicates? – Vasi

+0

@ nem035它被使用,但這只是一個簡化版本。我把它分解到相關部分。 req.files.sourceStrings用於創建'fileInformation' – kentor

回答

1

如果我讀model.save規格正確的貓鼬的網站,你保存的問題是,而你總是重用原來的項目,而不是新保存的項目應包含最新的狀態。

所以你基本上是這樣做的:

project.files.push(file1); 
// file1 is marked as new 
project.save(); 
project.files.push(file2); 
// file1 & file2 are marked as new 
// (the project doesn't know file1 has been saved already) 
// ... 

現在,這實際上帶來了相當一些優勢,因爲你正在一個做保存每個文件,同時可以爲您節省一次所有文件;)

我想最簡單的方法就是放置該項目。保存方法你以外的for循環和改變你的第一種方法一樣

function saveAssetInDatabase(project, fileInformation) { 
    let uploaded_file = {}; 
    uploaded_file = fileInformation; 
    uploaded_file.file_type = 'asset'; 
    uploaded_file.display_name = fileInformation.originalname; 
    project.uploaded_files.push(uploaded_file); 
} 

在for循環改爲

function saveSourceString(project, req) { 
    for(var i=0; i<req.files["sourceStrings"].length; i++) { 
     // Unknown file format, let's save it as asset 
     saveAssetInDatabase(project, fileInformation); 
    } 
    // save after all files were added 
    return project.save().then(result => { 
     return res.status(200).send() 
     }).catch(err => { 
     logger.error(err) 
     return res.status(500).send() 
     }); 
} 

注意project.save()會返回一個承諾,用包含新保存project參數。如果您希望稍後操作此對象,請確保您已保存文件,而不是像您至今所做的那樣保存未保存的模型

1

問題

每次在for循環中創建一個承諾然後發送到時候項目 對象。這不是正確的方法。每個承諾都已解決,您已將項目對象發送給數據庫然後將其存儲。

例如,您有3個資產詳細信息。 雖然第一次循環運行第一個資產數據將存儲在項目對象中,並且承諾已解決,但您已將該時間項目發送到數據庫存儲中。這次項目對象具有第一個資產細節。

雖然運行第二個資產數據的第二個時間循環將存儲在具有第一個資產數據的項目對象中,並且承諾解決,但您已將該時間項目發送到您的數據庫存儲中。這次項目對象具有第一和第二資產細節。

雖然第三次循環運行第三項資產數據將存儲在具有第一和第二資產數據的項目對象中,並且承諾解決,您已將該時間項目發送到您的數據庫存儲中。這次項目對象具有第一,第二和第三資產細節。

因此,您的數據庫中存儲了相同的數據。

解決方案

你必須使用Promise.all。將項目數據存儲在數據庫中後解決所有項目的承諾。

// your DB function 
    function saveAssetInDatabase(project, fileInformation) { 
     return new Promise((resolve, reject) => { 
      let uploaded_file = {} 
      uploaded_file = fileInformation 
      uploaded_file.file_type = 'asset' 
      uploaded_file.display_name = fileInformation.originalname 
      project.uploaded_files.push(uploaded_file) 
      project.save(); 
      resolve(); 
     }) 
    } 

    // calls function 

    let promiseArray = []; 
    for(var i=0; i<req.files["sourceStrings"].length; i++) { 
     promiseArray.push(saveAssetInDatabase(project, fileInformation)); 
    } 

    Promise.all(promiseArray).then(result => { 
     return res.status(200).send(); 
    }).catch(err => { 
     logger.error(err) 
     return res.status(500).send() 
    }) 
} 
+0

'promiseArray。(saveAssetInDatabase(project,fileInformation));'是一個錯字還是這種'.push'的某種ES6語法? – kentor

+0

對不起,這是我的錯誤。我會糾正它。 – Vasi

+0

更改了它。它是否有用? – Vasi