将对象推入对象数组

时间:2017-07-01 20:19:55

标签: javascript node.js mongoose ecmascript-6

问题:

我希望通过将每个上传文件的文件信息写入我的数据库来跟踪我上传的文件。但是当我上传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()
    })
}

我猜我的db函数有问题,因为它会导致重复的文件条目。我在这做错了什么?一个文件应该有一个条目。

2 个答案:

答案 0 :(得分:1)

<强>问题

每次在你的for循环中创建一个promise,然后发送你的那个时间项目 宾语。这不是正确的方式。每个承诺解决了您已将项目对象发送到DB然后存储它。

例如,您有3个资产详细信息。 虽然第一次运行第一个资产数据的第一次循环将存储在项目对象中并且解决了承诺,但您已将该时间项目发送到数据库中。这次项目对象有第一个资产详细信息。

第二次运行第二个资产数据的第二次循环将存储在具有第一个资产数据的项目对象中,并且已解决了承诺,您已在数据库中发送该时间项目。这次项目对象有第一和第二个资产详细信息。

虽然运行第三个资产数据的第三次循环将存储在具有第一个和第二个资产数据的项目对象中,并且解决了承诺,但您已在数据库中发送该时间项目。这次项目对象有第一,第二和第三个资产详细信息。

因此,您在数据库中存储了相同的数据。

<强>解决方案

您已使用Promise.all。将项目数据存储在数据库中后,解决所有assest的承诺。

    // 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()
    })
}

答案 1 :(得分:1)

如果我在mongoose网站上正确阅读了model.save上的规范,那么保存的问题在于您总是重复使用原始项目,而不是应该包含最新状态的新保存项目。 / p>

所以你基本上在做什么:

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)
// ...

现在,这实际上带来了一些优势,因为您当前正在执行每个文件的保存,而您可以一次保存所有文件;)

我想最简单的方法是将project.save方法放在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()将返回一个promise,其中一个参数包含新保存的project。如果您希望稍后操作此对象,请确保获取已保存的文件,而不是像以前那样使用未保存的模型