首页 > 解决方案 > 无法在承诺内调用 res.send()

问题描述

我正在使用回调重构我的代码。当然,第一个解决方案中的所有内容都按预期工作:

        const newUser = new User({
            email,
            password,
        })

        User.exists({ email }, (err, userExists) => {
            if (err) {
                return next(err)
            }
            if (userExists) {
                return res.status(400).send("A user with that email already exists")
            }
            newUser.save()
                .then(result => console.log('new user successfully registered!:', result))
                .catch(err => {
                    console.error('Cannot save user: ', err)
                })

            var profile = _.pick(req.body, 'email', 'password', 'extra')

            res.status(201).send({
                id_token: createIdToken(profile),
                access_token: createAccessToken()
            })
        })

这是重构之后:

        User.exists({ email })
            .then(userExists => {
                if (userExists) {
                    res.status(400).send("A user with that email already exists")
                }
            })
            .then(() => {
                const newUser = new User({
                    email,
                    password,
                })
                return newUser
            })
            .then(newUser => {
                console.log('newUser: ', newUser);
                return newUser.save()
            })
            .then(result => console.log('new user successfully registered!:', result))
            .catch(err => {
                console.error('Cannot save user: ', err)
                return next(err)
            })

但是,这不起作用。我已经隔离了承诺链中发生错误的位置,并且在我尝试将响应发送回客户端时发生res.send

我得到的错误是:C

无法保存用户:错误:发送后无法设置标题。在 validateHeader (_http_outgoing.js:491:11) 在 ServerResponse.setHeader (_http_outgoing.js:498:3) 在 ServerResponse.header (/home/kyle/programming/projects/never-forget/server/node_modules/express/lib/ response.js:771:10) 在 ServerResponse.send (/home/kyle/programming/projects/never-forget/server/node_modules/express/lib/response.js:170:12) 在 /home/kyle/programming/ projects/never-forget/server/src/controllers/users.js:47:22 at process._tickDomainCallback (internal/process/next_tick.js:229:

cannot set headers after they are sent是不言自明的,但是我看不到在发送请求后我尝试在程序中的哪个位置发送标头。看到res.send请求结束,我看不出还应该包括什么。

标签: expressmongoosepromise

解决方案


我能想到的问题是:

在回调实现中,当userExists为真时,您正在调用return res.status(400).send("A user with that email already exists")结束回调并且res.status(201).send({...})不会被调用。

但是,在 promise 实现中,当userExists为真时,它们都会被调用。

所以,你可以在 之后抛出一个错误return res.status(400).send("A user with that email already exists"),并在 catch 块中捕获它,它将结束主回调,即通过return next(err);


推荐阅读