Express对接MongoDB时通过ID查询单条数据返回404问题
问题原因及修复方案
你遇到的404错误及接口异常由以下3个可修复的问题导致:
- 路由匹配规则错误:路由文件中定义单条资源路径时缺少前置斜杠,Express路由匹配规则下,
router.route(':id')无法命中/api/v1/bootcamps/xxx格式的请求,直接返回404。 - Mongoose方法传参不规范:
getBootcamp控制器中findById方法直接传入id字符串即可,不需要封装为{_id: req.params.id}对象,不符合Mongoose官方调用规范,容易触发查询异常。 - 代码拼写错误:
updateBootcamp、deleteBootcamp方法中多次出现res.statuc的拼写错误,正确拼写为res.status,会导致接口异常时抛出运行时错误。
修复后代码示例
1. routes/bootcamps.js(路由文件)
const express = require('express') const { getBootcamp, getBootcamps, createBootcamps, updateBootcamp, deleteBootcamp } = require('../controllers/bootcamps') const router = express.Router() router.route('/').get(getBootcamps).post(createBootcamps) // 新增路径前置斜杠 router.route('/:id').put(updateBootcamp).delete(deleteBootcamp).get(getBootcamp) module.exports = router
2. controllers/bootcamps.js(控制器文件)
const Bootcamp = require('../models/Bootcamp') exports.getBootcamps = async (req, res, next) => { try { const bootcamps = await Bootcamp.find() res.status(200).json({success: true, count: bootcamps.length, data: bootcamps}) } catch (error) { res.status(400).json({success: false}) } } // 修正传参问题 exports.getBootcamp = async (req, res, next) => { try { // 直接传入id字符串即可 const bootcamp = await Bootcamp.findById(req.params.id) if (!bootcamp) { // 找不到资源返回404更符合REST规范 return res.status(404).json({success: false}) } res.status(200).json({success: true, data: bootcamp}) } catch (error) { res.status(400).json({success: false}) } } exports.createBootcamps = async (req, res, next) => { try { const bootcamp = await Bootcamp.create(req.body) res.status(201).json({ success: true, data: bootcamp, msg: 'Bootcamp created' }) } catch (error) { console.log(error) res.status(400).json({success: false}) } } // 修正拼写错误 exports.updateBootcamp = async (req, res, next) => { try { const bootcamp = await Bootcamp.findByIdAndUpdate(req.params.id, req.body, { new: true, runValidators: true }); if (!bootcamp) { // statuc改为status return res.status(404).json({success: false}) } res.status(200).json({ success: true, data: bootcamp }) } catch (error) { // statuc改为status return res.status(400).json({success: false}) } } // 修正拼写错误 exports.deleteBootcamp = async (req, res, next) => { try { const bootcamp = await Bootcamp.findByIdAndDelete(req.params.id); if (!bootcamp) { // statuc改为status return res.status(404).json({success: false}) } res.status(200).json({ success: true, data: {} }) } catch (error) { // statuc改为status return res.status(400).json({success: false}) } }
修改完成后重启服务即可正常请求单条资源接口。
内容的提问来源于stack exchange,提问作者Daniel Chikaka
相关产品推荐
相关产品推荐

