getContact API调用无报错持续运行问题的修复咨询
问题根源分析
- 冗余await导致逻辑异常:
getContact中const ret = await Contact.findById(...)已经获取了查询结果,但后续if(!(await ret))再次对非Promise对象使用await,属于逻辑错误;当查询结果为null时,这个判断可以直接简化。 - 未处理ID格式错误的异常:传入无效MongoDB ObjectId格式的ID时,
Contact.findById会抛出CastError,此时res.statusCode未被设置,errorHandler会进入500分支,但该分支使用了不存在的err.stackTrace属性,且错误未被正确收尾导致请求挂起。 - errorHandler的default分支未结束响应:进入default分支时仅打印日志,未发送响应,导致客户端请求一直处于pending状态。
- 错误堆栈属性调用错误:所有分支中使用
err.stackTrace,但Error对象的标准堆栈属性是err.stack。
修复步骤
1. 修正getContact的判断逻辑
移除冗余await,直接判断查询结果:
//@desc Get contact //@route GET api/contacts/:id //@access public const getContact = asyncHandler(async (req,res) => { const ret = await Contact.findById(req.params.id) console.log(ret); // Line 6 if(!ret){ // 移除多余的await res.status(404); throw new Error("Contact not found"); } res.status(200).json(ret); });
2. 修复errorHandler的错误处理逻辑
- 替换
err.stackTrace为标准的err.stack - 在default分支中强制发送响应,避免请求挂起
- 新增
CastError处理,将ID格式错误归类为400 Bad Request:
// In this componenet, all errors of this application will be dealt with. //Import constants for cleaner error handling const constants = require("../constants"); // Errors consist of error, response, request and the next function const errorHandler = (err, req, res, next) =>{ // 优先处理特定类型错误 if (err.name === 'CastError') { res.status(400); err.message = `无效的ID格式: ${err.value}`; } // 确定响应状态码 const status = res.statusCode ? res.statusCode : 500; switch(status){ case 400: res.json({ title: "BAD REQUEST", message: err.message, stackTrace: err.stack }); break; case 404: res.json({ title: "NOT FOUND", message: err.message, stackTrace: err.stack }); break; case 403: res.json({ title: "FORBIDDEN REQUEST", message: err.message, stackTrace: err.stack }); break; case 401: res.json({ title: "UNAUTHORIZED", message: err.message, stackTrace: err.stack }); break; case 500: res.json({ title: "SERVER ERROR", message: err.message, stackTrace: err.stack }); break; default: // 发送默认响应,避免请求挂起 res.status(500).json({ title: "UNHANDLED ERROR", message: err.message || "发生了未预期的错误", stackTrace: err.stack }); console.log("Error Handler working..."); break; }; }; module.exports = errorHandler;
3. 可选:提前验证ID格式
在控制器中提前验证ID有效性,避免无效查询:
// 引入mongoose工具类 const mongoose = require('mongoose'); const getContact = asyncHandler(async (req,res) => { // 提前验证ID格式 if (!mongoose.Types.ObjectId.isValid(req.params.id)) { res.status(400); throw new Error("无效的联系人ID格式"); } const ret = await Contact.findById(req.params.id) console.log(ret); // Line 6 if(!ret){ res.status(404); throw new Error("未找到联系人"); } res.status(200).json(ret); });
验证修复效果
- 传入格式正确但不存在的ID:返回404响应,提示"未找到联系人"
- 传入格式错误的ID:返回400响应,提示"无效的联系人ID格式"
- 所有错误场景都会正确返回响应,不会出现请求持续挂起的情况
内容的提问来源于stack exchange,提问作者Eraserhead_18
相关产品推荐
相关产品推荐

