【问题标题】:Why does using mongoose callback result in saving data twice?为什么使用猫鼬回调会导致两次保存数据?
【发布时间】:2019-06-09 06:28:33
【问题描述】:

我一直想知道为什么向 mongoose findOneAndUpdate 函数添加回调会导致将数据两次保存到 DB 中?

public async addPersonAsFavorite(userId: string, friendId: string) {
    if (!await this.isPersonAlreadyFriend(userId, friendId)) {
      const friendList = FriendsList.findOneAndUpdate(
        { _id: userId },
        { $push: { friendsList: friendId } },
        { upsert: true, new: true },
        (err, data) => {
         if (err) console.error(err);
         return data;
        }
      );
      return friendList;
    }}

  public async isPersonAlreadyFriend(userId: string, friendId: string) {
    let isFriendFound = false;
    await FriendsList.findById(userId, (err, data) => {
      if (data) {
        console.log(data.friendsList);
      }
      if (err) console.error(err);
      if (data && data.friendsList.indexOf(friendId) > -1) {
        isFriendFound = true;
        console.log('already friend');
      } else {
        console.log('not friend');
        isFriendFound = false;
      }
    })
    return isFriendFound;
  }

如果我删除回调,数据只会保存一次。

编辑:添加了第二段代码和新问题。 如果有人向按钮发送垃圾邮件以添加朋友。该朋友将被添加多次,因为在添加第一个朋友之前,可以进行检查以防止这种情况,它已经多次添加了该人。

在允许再次调用该函数之前,我如何确保它完成了对 DB 的写入?

【问题讨论】:

  • 你那里为什么有回调..?只需添加等待..

标签: javascript mongodb express mongoose


【解决方案1】:

也许问题出在 isPersonAlreadyFriend 方法中,因为您尝试使用 async await 调用它,但随后您传递了一个回调,导致该方法不返回承诺。在 mongodb 中使用 Promise 的正确方法应该是这样的:

public async isPersonAlreadyFriend(userId: string, friendId: string) {
    let isFriendFound = false;
    const data = await FriendsList.findById(userId);
    if (data) {
      console.log(data.friendsList);
    }
    if (data && data.friendsList.indexOf(friendId) > -1) {
      isFriendFound = true;
      console.log('already friend');
    } else {
      console.log('not friend');
      isFriendFound = false;
    }
    return isFriendFound;
  }

试试这个,如果有帮助,请告诉我

【讨论】:

  • 啊,我明白了。承诺需要在进行检查之前解析为变量,然后它将返回承诺。额外的问题。我怎样才能防止这样的功能被垃圾邮件?如果有人每秒多次调用该函数,在更新函数完成并返回true之前,他们都会被添加为好友?
  • 就是这样,否则你总是在变量中返回 false。
  • 我唯一能找到的关于防止此类功能的垃圾邮件是前端禁用按钮或锁定功能。这些是防止此类问题的最佳方法吗?
  • 也许您可以通过简单的查找来更改 findById 并稍微简化代码: const data = await FriendsList.findById({userId, friendsList:friendId});这应该只在用户存在并且有朋友的情况下才返回用户。也许你可以在更新中使用类似的东西,同时检查 userId 是那个并且它还没有朋友。像这样的东西: FriendsList.findOneAndUpdate({ _id: userId, $not: {friendsList:friendId} }, 检查类似的东西是否可以工作 ;)
  • 谢谢你的回答。我会仔细看看的。与此同时,我刚刚根据 Id 锁定了函数。
猜你喜欢
  • 1970-01-01
  • 2013-08-05
  • 2017-03-02
  • 2015-05-09
  • 1970-01-01
  • 1970-01-01
  • 2016-05-05
  • 2013-06-07
  • 2020-02-14
相关资源
最近更新 更多