即使在 return 之后函数仍继续执行

Function continues execution even after return

我的问题很简单,当我运行下面的代码和检查数据库时,我发现用户被成功删除,这意味着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;
    };
  });

我的问题是:为什么会发生这种行为?为什么执行已经跳到函数的底部了?还有为什么走到函数底部响应的时候,删除是怎么发生的,在DB中删除了User,我这里比较迷惑。

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

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

如果仔细观察,由于内部查询是异步的,因此甚至在触发内部删除查询之前就触发了这一行。

所以在第一种情况下,无论用户是否存在,函数总是returns响应。

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

EDIT : Alternative Code Using Async-Await

在这种情况下使用 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 - 您可以为 User.exists API 设置类似的 async-await,前提是其父函数标记为 async.

希望对您有所帮助。

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