У меня одинаковая логика для двух маршрутов в этом коде, но они ведут себя по-разному - PullRequest
2 голосов
/ 18 апреля 2019
// @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 }));
});

У меня есть эти два маршрута, как указано выше. Первый - это поиск пользователя из дБ с помощью дескриптора (имя пользователя), а второй - поиск по user_id, созданному самим дБ. Когда я запрашиваю 1-й маршрут, используя неправильный дескриптор, выполняется блок 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"
    }
}

Логика одинакова для обоих маршрутов, но они реагируют по-разному. В чем причина этого ???

если вы хотите посмотреть схему профиля, вот она:

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.

Ответы [ 2 ]

0 голосов
/ 18 апреля 2019

проверьте сообщение об ошибке

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

user поле имеет тип mongodb ObjectId, и вы предоставляете String, в то время как handle имеет тип String

В случае запроса handle ошибки не было, только в вашем db не было записи.

Вы можете исправить это как mongoose.Types.ObjectId(req.params.user_id). Подробнее здесь

Также существует проблема с вашим кодом.(Выполнение не останавливается там, где вы думаете, что оно останавливается, и вы получаете необработанное отклонение обещания) *

.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);
}
0 голосов
/ 18 апреля 2019

Я думаю, что во втором маршруте вы пытаетесь выполнить запрос с недопустимым ObjectID.

Проверка Pls: Что такое ошибка Mongoose Не удалось выполнить приведение к ObjectId для значения XXX по пути "_id"?

...