0

我的问题很简单,当我运行以下代码并检查数据库时,我发现用户已成功删除,这意味着User.findOneAndDelete已执行,承诺已履行,我希望{ success: 'user_deleted' }在响应中看到;但是,我得到{ error: 'user_not_found' }的只有当用户不存在时才应该发生这种情况,这里不是这种情况,因为 IF 块内的代码是根据我在数据库中的观察执行的。

User.exists({ username}).then(exists => {
    if (exists) {
      User.findOneAndDelete({ username }).then(() => {
        res.json({ success: 'user_deleted' });
        return;
      }
      ).catch(err => {
        res.json({ error: 'user_delete_fail' });
        return;
      })
    };
    res.json({ error: 'user_not_found' })
    return;
  });

现在为了解决这个问题,我尝试添加一个else语句,而不是我之前做的隐式方式,它按预期工作,我在响应中得到了 `{ success: 'user_deleted' }。

User.exists({ username}).then(exists => {
    if (exists) {
      User.findOneAndDelete({ username }).then(() => {
        res.json({ success: 'user_deleted' });
        return;
      }
      ).catch(err => {
        res.json({ error: 'user_delete_fail' });
        return;
      })
    } else {
      res.json({ error: 'user_not_found' })
      return;
    };
  });

我的问题是:为什么会发生这种行为?为什么执行已经跳到函数的底部?以及为什么当它走到函数底部并响应时,删除是如何发生的,用户在数据库中被删除,我在这里很困惑。

编辑:当我将父函数转换为async函数并在 DB 操作上使用 await 时,它的行为也符合预期。

4

2 回答 2

2

您的代码的问题是最后一次res.json({ error: 'user_not_found' })调用。

如果你仔细看,这一行甚至在内部删除查询被触发之前就被触发了,因为内部查询是异步的。

因此,在第一种情况下,无论用户是否存在,该函数总是返回响应。

将 else 放入您的代码块中基本上会执行either this or that逻辑,因此如果用户存在,res.json({ error: 'user_not_found' })则永远不会被调用。

编辑:使用异步等待的替代代码

在这种情况下使用async-await会更有意义,因为它可以简化代码,请检查以下代码,它应该完全符合您的要求,而无需使用else.

它还避免了嵌套,使代码更简单

User.exists({ username }).then(async exists => {
    try {
        if (exists) {
            // this await will remove the need of inner promise chaining
            await User.findOneAndDelete({ username });
            res.json({ success: 'user_deleted' });
        }
        // in this case, this will no longer be performed before delete query
        res.json({ error: 'user_not_found' });
    } catch (error) {
        res.json({ error: 'user_delete_fail' });
    }
});

PS-如果其父函数标记为,您可以有类似async-await的API 。User.existsasync

我希望这有帮助。

于 2020-07-11T21:59:30.847 回答
1

findOneAndDelete返回 a Promise,它不会阻止剩余代码的执行(除非,正如您所指出的,该函数是async并且您等待它)。此外,您不会从 if 分支返回(return在内部then只会从回调中返回then),因此外部的剩余代码将以任何方式执行。它可能仅在您等待(没有return)时才有效,因为此时已经发送了响应。

于 2020-07-11T22:07:51.630 回答