承诺关闭的 NodeJS UnhandledPromiseRejectionWarning

NodeJS UnhandledPromiseRejectionWarning with promises closed

我 运行 在实施使用令牌的注册系统以防止 运行dom 用户创建多个帐户时遇到问题。

代码一直运行到最后,响应按预期工作,但之后我收到一条警告,内容为: UnhandledPromiseRejectionWarning: 错误 [ERR_HTTP_HEADERS_SENT]: 发送给客户端后无法设置 headers

它说问题发生在第44行,这是mongoose save方法的catch语句。

newRegistrationToken.save()
            .then(newRegistrationToken => res.status(200).json(newRegistrationToken))
            .catch(err => res.status(500).json(err));

我一直在寻找解决方案,答案总是缺少 catch 语句,导致出现此警告。但是,在我的代码中,我没有看到任何遗漏的 catch 语句,所以我在这里有点迷路。

完整路线如下:

router.post('/create', (req, res) => {
    const { errors, isValid } = validateRegistrationToken(req.body);
    if(!isValid) return res.status(400).json(errors);

    // Searching for an active token associated with the e-mail address given
    console.log("search for active token");
    ModelRegistrationToken.findOne({
        email: req.body.email,
        expiresAt: { $gte: Date.now() }
    }).then(user => {
        // if user found
        if(user){
            // check if the user is already registered
            console.log("search for registered user");
            ModelUser.findOne({email: user.email}).then((registered) => {
                if(registered)
                    return res.status(400).json({email: 'There\'s a user already registered with the e-mail address given'});
                return res.status(400).json({email: 'The address given already has an active registration token'});
            }).catch(err => console.log(err));
        }
        
        // Otherwise create a new token
        const newRegistrationToken = new ModelRegistrationToken({
            email: req.body.email,
            expiresAt: new Date(Date.now() + Number.parseInt(config.REG_TOKEN_EXPIRATION_PERIOD) * 24 * 60 * 60 * 1000)
        });
        console.log("save token");
        newRegistrationToken.save()
            .then(newRegistrationToken => res.status(200).json(newRegistrationToken))
            .catch(err => res.status(500).json(err));
        
    }).catch(err => res.status(500).json(err));
});

我似乎无法解决这个问题,因此非常感谢您对此的帮助..

您有:

if (user) {
  // do stuff and call res.json
}
// do other stuff and call res.json

如果user存在,res.json将被调用两次。尝试在 if (user) 块的底部返回:

if (user) {
  // check if the user is already registered
  console.log("search for registered user");
  ModelUser.findOne({
    // ...
  }).catch(err => console.log(err));
  return; // <---------------------------------
}

// Otherwise create a new token
const newRegistrationToken = new ModelRegistrationToken({
  email: req.body.email,
  expiresAt: new Date(Date.now() + Number.parseInt(config.REG_TOKEN_EXPIRATION_PERIOD) * 24 * 60 * 60 * 1000)
});
// ...

如果内部 findOne 发生错误,我还建议发送状态 500,否则响应将挂起:turn

}).catch(err => console.log(err));

变成类似

的东西
}).catch(err => res.status(500).json(err));

就像你在其他地方做的那样。