【问题标题】:Node.js res.send VS res.end VS return res.endNode.js res.send VS res.end VS 返回 res.end
【发布时间】:2018-05-20 18:45:48
【问题描述】:

我的以下代码在 mongodb findAndUpdateOne 更新查询中有语法错误。

router.post('/buylicense', isLoggedIn, function(req, res) {
    if (!req.body.cid) {
        return res.send('failed');
    }
    Company.findOne({
        ownedBy: req.user.local.username,
        _id: req.body.cid
    }, function(err, result) {
        if (err) {
            return res.send('failed');
        }
        if (result.license) {
            return res.send('valid');
        } else {
            Company.findOneAndUpdate({
                ownedBy: req.user.local.username,
                _id: req.body.cid
            }, {
                license: true,
                licenseExpireDate: {
                    $add: ["$date", 3 * 24 * 60 * 60000] // bad code, a problem for another day
                }
            }, function(err) {
                if (err) {
                  console.log(err);
                  return res.end('failed'); // Code should stop here.
                }
                console.log('got here');
                return res.send('success');
            });
        }
    });
    console.log('How did I get here?');
    res.send('failed');
});

我的问题是为什么代码到达了代码的最后部分:

 console.log('How did I get here?');
 res.send('failed');

如果我使用 return res.end 以外的任何内容,代码将到达末尾并导致我的应用程序崩溃。简单地做res.end 不起作用,return res.send 也不起作用。 return 或至少 res.end 不应该足以真正阻止代码到达末尾吗?

如果我不停止right way 的错误,则会显示错误,可能不相关但在这里:

How did I get here?
{ CastError: Cast to date failed for value "[object Object]" at path "licenseExpireDate"
    at MongooseError.CastError (/media/node_modules/mongoose/lib/error/cast.js:19:11)
    at SchemaDate.cast (/media/node_modules/mongoose/lib/schema/date.js:242:9)
    at SchemaDate.castForQuery (/media/node_modules/mongoose/lib/schema/date.js:276:17)
    at Query._castUpdateVal (/media/node_modules/mongoose/lib/query.js:2477:17)
    at Query._walkUpdatePath (/media/node_modules/mongoose/lib/query.js:2372:25)
    at Query._castUpdate (/media/node_modules/mongoose/lib/query.js:2296:23)
    at castDoc (/media/node_modules/mongoose/lib/query.js:2500:18)
    at Query._findAndModify (/media/node_modules/mongoose/lib/query.js:1755:17)
    at Query._findOneAndUpdate (/media/node_modules/mongoose/lib/query.js:1622:8)
    at /media/node_modules/kareem/index.js:156:8
    at args (/media/node_modules/kareem/index.js:71:20)
    at Query.<anonymous> (/media/node_modules/mongoose/lib/schema.js:728:7)
    at next (/media/node_modules/kareem/index.js:82:14)
    at Kareem.execPre (/media/node_modules/kareem/index.js:99:3)
    at Kareem.wrap (/media/node_modules/kareem/index.js:146:8)
    at Query._findOneAndUpdate (/media/node_modules/kareem/index.js:188:11)
  message: 'Cast to date failed for value "[object Object]" at path "licenseExpireDate"',
  name: 'CastError',
  kind: 'date',
  value: { '$add': [ '$date', 259200000 ] },
  path: 'licenseExpireDate',
  reason: undefined }
got here
_http_outgoing.js:346
    throw new Error('Can\'t set headers after they are sent.');
    ^

Error: Can't set headers after they are sent.
    at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:346:11)
    at ServerResponse.header (/media/node_modules/express/lib/response.js:718:10)
    at ServerResponse.send (/media/node_modules/express/lib/response.js:163:12)
    at /media/sf_vShared/xyz/app/modalRoutes.js:461:28
    at /media/node_modules/kareem/index.js:160:11
    at Query._findAndModify (/media/node_modules/mongoose/lib/query.js:1767:14)
    at Query._findOneAndUpdate (/media/node_modules/mongoose/lib/query.js:1622:8)
    at /media/node_modules/kareem/index.js:156:8
    at args (/media/node_modules/kareem/index.js:71:20)
    at Query.<anonymous> (/media/node_modules/mongoose/lib/schema.js:728:7)
    at next (/media/node_modules/kareem/index.js:82:14)
    at Kareem.execPre (/media/node_modules/kareem/index.js:99:3)
    at Kareem.wrap (/media/node_modules/kareem/index.js:146:8)
    at Query._findOneAndUpdate (/media/node_modules/kareem/index.js:188:11)
    at Query.findOneAndUpdate (/media/node_modules/mongoose/lib/query.js:1611:15)
    at Function.Model.findOneAndUpdate (/media/node_modules/mongoose/lib/model.js:1491:13)
[nodemon] app crashed - waiting for file changes before starting...

【问题讨论】:

  • Mongoose 的 find 函数是异步的,这意味着它们独立于主线程和后台运行。调用Company.findOne 之后的代码会立即运行,您不应该在那里 res.end/send。而是像你已经做的那样在回调上这样做。
  • 因此,对于任何猫鼬操作,阻止整个代码继续运行的方法是使用 return res.end 还是有更好的方法?
  • return 结束任何函数,这对于 express 或 mongoose 来说并不是什么特别的东西。 res.sendend 是为客户端返回数据的快速函数。

标签: node.js mongodb express


【解决方案1】:

首先我们看看ExpressJS的三个函数有什么区别

res.end: 来自 NodeJS 核心。在 Express JS 中,如果您需要快速结束请求并且不需要发送任何数据,则可以使用此功能

res.send:发送数据并结束请求

res.json 以 JSON 格式发送数据并结束请求。

我的问题是为什么代码会到达代码的最后一部分:?

我希望你知道 JavaScript 是异步语言。使用 Mongoose 对 MongoDB 的所有数据库调用都是异步的。所以Compnay.findOne 是一个异步函数调用,它一直处于事件循环中,直到数据库读取操作未完成。作为 JS 的异步行为,JS 主线程执行不会等待 DB 函数结果返回(无阻塞)并到达最后一行,并且您的请求以调用 res.end("failed") 结束但是当 DB 读取操作完成时返回数据然后你再次打电话给res.send 并以Error: Can't set headers after they are sent. 结束

希望这会有所帮助:)

【讨论】:

  • @Trax return res.send()return res.end() 应该具有相同的效果。但我更喜欢使用文档:-)
  • 那是我的问题,为什么两者的效果不一样。
  • 除了上面的答案之外,Node 的异步特性可能会导致即使不使用 Promise,也会执行超过 res.send() 函数的额外代码行。
猜你喜欢
  • 2015-06-15
  • 1970-01-01
  • 1970-01-01
  • 2019-09-28
  • 2013-12-19
  • 2013-10-03
  • 2013-02-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多