【问题标题】:I have the same logic for two routes in this code , but they behave differently我对这段代码中的两条路线有相同的逻辑,但它们的行为不同
【发布时间】:2019-09-08 21:20:01
【问题描述】:
// @route   GET api/profile/handle/:handle
// @desc    Get profile by handle
// @access  Public

router.get('/handle/:handle', (req, res) => {
    const errors = {};

    Profile.findOne({ handle: req.params.handle })
        .populate('user', ['name', 'avatar'])
        .then(profile => {
            //console.log('profile1 ' + profile);
            if (!profile) {
                errors.noprofile = 'There is no profile for this user for handle route (from then block)';
                res.status(404).json(errors);
            }
            res.json(profile);
        })
        .catch(err => res.status(404).json({ profile: 'There is no profile for this user for handle route (from error block)' }));

});

// @route   GET api/profile/user/:user_id
// @desc    Get profile by user ID
// @access  Public

router.get('/user/:user_id', (req, res) => {
    const errors = {};

    Profile.findOne({ user: req.params.user_id })
        .populate('user', ['name', 'avatar'])
        .then(profile => {
            // console.log('profile not found by userid');
            //console.log('profile2 ' + profile);
            if (!profile) {
                errors.noprofile = 'There is no profile for this user for user_id route (from then block)';
                res.status(404).json(errors);
            }
            res.json(profile);
        })
        .catch(err => res.status(404).json({ profile: 'There is no profile for this user for user_id route (from error block)',
err: err }));
});

我有上述两条路线。第一个是使用句柄(用户名)从 dB 中搜索用户,第二个是使用 dB 本身创建的 user_id 进行搜索。当我使用错误的句柄请求第一条路由时, then() 块被执行并且我得到了这个响应:

{
    "noprofile": "There is no profile for this user for handle route (from then block)"
}

但是在第二条路线中(通过 user_id 搜索),当我输入错误的 user_id 时,catch 块被执行并且我得到了这个响应:

{
    "profile": "There is no profile for this user for user_id route (from error block)",
    "err": {
        "message": "Cast to ObjectId failed for value \"5cb0ec06d1d6f93c20874427rhdh\" at path \"user\" for model \"profile\"",
        "name": "CastError",
        "stringValue": "\"5cb0ec06d1d6f93c20874427rhdh\"",
        "kind": "ObjectId",
        "value": "5cb0ec06d1d6f93c20874427rhdh",
        "path": "user"
    }
}

两条路线的逻辑相同,但它们的响应不同。这背后的原因是什么???

如果你想看看 Profile 架构,这里是:

const ProfileSchema = new Schema({
    user: {
        type: Schema.Types.ObjectId,
        ref: 'users'
    },
    handle: {
        type: String,
        required: true,
        max: 40
    },
    company: {
        type: String
    },
   ....
....
.....
});

我在请求错误句柄时也收到了警告,如下所示:

(node:16996) UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
    at ServerResponse.setHeader (_http_outgoing.js:470:11)
    at ServerResponse.header (H:\MERN Stack Course\devConnector\node_modules\express\lib\response.js:767:10)
    at ServerResponse.send (H:\MERN Stack Course\devConnector\node_modules\express\lib\response.js:170:12)
    at ServerResponse.json (H:\MERN Stack Course\devConnector\node_modules\express\lib\response.js:267:15)
    at Profile.findOne.populate.then.catch.err (H:\MERN Stack Course\devConnector\routes\api\profile.js:75:39)
    at process._tickCallback (internal/process/next_tick.js:68:7)
(node:16996) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:16996) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

【问题讨论】:

    标签: node.js mongodb express jwt passport.js


    【解决方案1】:

    检查错误信息

    "message": "Cast to ObjectId failed for value \"5cb0ec06d1d6f93c20874427rhdh\" at path \"user\" for model \"profile\""
    

    user 字段是 mongodb 类型 ObjectId 并且您提供 StringhandleString 类型

    如果handle查询没有错误,只是你的db中没有条目。

    您可以像mongoose.Types.ObjectId(req.params.user_id) 一样修复它。 More here

    另外,您的代码也有问题。 (执行不会在您认为它停止的地方停止,并且您会收到未处理的承诺拒绝)

    .then(profile => {
      //console.log('profile1 ' + profile);
      if (!profile) { // <--- if true
        errors.noprofile = 'There is no profile for this user for handle route (from then block)';
        res.status(404).json(errors); // <-- executes
      }
      res.json(profile); // <--- always executes within then callback
    })
    

    如果此检查 if (!profile) 计算结果为 true,则执行 res.status(404).json(errors)。然后执行下一个res.json(profile)

    在您的代码中,res.json(profile) 总是在没有错误时执行。您可以通过使用return 停止执行或if..else 来纠正:

    return res.status(404).json(errors);
    
    // or
    if (!profile) {
      errors.noprofile = 'There is no profile for this user for handle route (from then block)';
      res.status(404).json(errors);
    } else {
      res.json(profile);
    }
    

    【讨论】:

    • 更新答案,查看
    【解决方案2】:

    我认为在您的第二条路线中,您尝试使用无效的 ObjectID 进行查询。

    请查收:What's Mongoose error Cast to ObjectId failed for value XXX at path "_id"?

    【讨论】:

    • 是的,这就是我的问题,我故意使用错误的 user_id 请求。问题是当我使用错误的句柄请求时,它会执行 then() 块,但在第二条路由的情况下,当我使用错误的 user_id 请求时,它会执行 catch() 块。
    • 你误会了。我知道这是故意错的。但是它的类型是无效的。这就是你得到 CastError 的原因。请检查: const valid = mongoose.Types.ObjectId.isValid(req.params.user_id);
    • 但是我对它会出现什么类型的错误不感兴趣,我想知道为什么它在第一条路由中没有抛出任何错误,两者具有相同的逻辑。而且我用错误的数字和字符串类型的 user_id 对此进行了测试,它说的是相同的转换错误。
    猜你喜欢
    • 2019-10-09
    • 1970-01-01
    • 2021-10-03
    • 2022-11-27
    • 2017-01-17
    • 1970-01-01
    • 2013-01-12
    • 1970-01-01
    • 2021-12-03
    相关资源
    最近更新 更多