【问题标题】:Push objects into object array将对象推入对象数组
【发布时间】:2017-12-05 12:18:46
【问题描述】:

问题:

我想通过将每个上传文件的文件信息写入我的数据库中来跟踪我上传的文件。但是,当我上传 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 函数有问题,因为它会导致重复的文件条目。我在这里做错了什么?一个文件应该有一个条目。

【问题讨论】:

  • 使用req.files.sourceStrings 作为循环条件但不在循环本身中使用它有什么意义?您现在总是保存相同的资产
  • 确保您的 req.files['sourseStrings'] 没有重复项?
  • @nem035 它被使用,但这只是一个简化版本。我把它削减到相关部分。 req.files.sourceStrings 用于创建fileInformation

标签: javascript node.js mongoose ecmascript-6


【解决方案1】:

如果我在 mongoose 网站上正确阅读了 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)
// ...

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

我想最简单的方法是将 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。如果您想在以后操作此对象,请确保您使用已保存的文件,而不是像您现在所做的那样,使用未保存的模型

【讨论】:

    【解决方案2】:

    问题

    每次在你的 for 循环中创建一个承诺,然后发送你那个时间的项目 目的。这不是正确的方法。解决的每个承诺都已将项目对象发送到数据库,然后将其存储。

    例如,您有 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()
        })
    }
    

    【讨论】:

    • promiseArray.(saveAssetInDatabase(project, fileInformation)); 是错字还是.push 的某种 ES6 语法?
    • 它执行得很好,但问题仍然存在 - 就像以前一样。不过感谢 Promise.all 的提示,我应该使用它是对的
    • 另外我认为我不需要在我的saveAssetInDatabase 中做resolve(),因为它已经是猫鼬的承诺了。如果成功它会自动拒绝,如果失败则拒绝,不是吗?!
    • mongoose 承诺如何拒绝您的 saveAssetInDatabase 承诺?
    • 我认为如果它在project.save()期间抛出异常会拒绝
    猜你喜欢
    • 2016-05-09
    • 2023-03-29
    • 1970-01-01
    • 2023-03-14
    • 1970-01-01
    • 2011-02-13
    • 2012-10-21
    • 2018-11-08
    相关资源
    最近更新 更多