You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React+Node+SQL Server应用GET请求出现500内部服务器错误排查

问题描述

在React+Node+SQL Server应用中,输入订单号触发GET请求http://localhost:5000/api/customerOrder/141798时出现500(Internal Server Error)。该订单号在数据库中存在,且通过POSTMAN调用该GET接口能正常返回数据。以下是相关代码,请求排查问题并给出修复方案:

dboperations.js

var config = require('./dbconfig');
const sql = require('mssql');
const { response } = require('express');

async function getallcustomerOrders(){
    try{
        let pool = await sql.connect(config);
        let orders = await pool.request()
            .query("SELECT * FROM [100].[dbo].[OELINCMT_SQL] order by ID desc");
        return orders.recordsets;
    }
    catch (error){
        console.log(error);
    }
}

async function getcustomerOrders(orderNumber) {
    try {
        let pool = await sql.connect(config);
        let orders = await pool.request()
            .input('input_parameter', sql.NChar, orderNumber)
            .query("SELECT ID,cmt FROM [100].[dbo].[OELINCMT_SQL] where LTRIM(ord_no) = LTRIM(@input_parameter)");
        return orders.recordsets;
    }
    catch (error) {
        console.log(error);
    }
}

async function updateComments(ID) {
    try {
        let pool = await sql.connect(config);
        let orders = await pool.request()
            .input('ID', sql.NChar, ID)
            .query(`SELECT cmt FROM [100].[dbo].[OELINCMT_SQL] WHERE ID = @ID`);

        let order = orders.recordset.length ? orders.recordset[0] : null;
        if (order) {
            await pool.request()
                .input('cmt', req.body.cmt)
                .query(`UPDATE [100].[dbo].[OELINCMT_SQL] SET cmt = @cmt WHERE ID = @ID;`);

            order = { ...order, ...req.body };

            response.json(order);
        } else {
            response.status(404).json({
                message: 'Record not found'
            });
        }
    } catch (error) {
        response.status(500).json(error);
    }
}

module.exports = {
    getallcustomerOrders : getallcustomerOrders,
    getcustomerOrders : getcustomerOrders,
    updateComments : updateComments
}

api.js

var Db = require('./dboperations');
var dboperations = require('./dboperations');

var express = require('express');
var bodyParser = require('body-parser');
var cors = require('cors');
const { request, response } = require('express');
var app = express();
var router = express.Router();

app.use(bodyParser.urlencoded({ extended: true}));
app.use(bodyParser.json());
app.use(cors());
app.use('/api', router);

router.use((request,response,next)=> {
    console.log('middleware');
    next();
})

router.route('/customerOrder').get((request,response)=>{
    dboperations.getallcustomerOrders().then(result => {
        response.json(result[0]);
        console.log(result[0]);
    })
})

router.route('/customerOrder/:orderNumber').get((request,response)=>{
    dboperations.getcustomerOrders(request.params.orderNumber).then(result => {
        response.json(result[0]);
        console.log(result[0]);
    })
})

router.route('/customerOrder/:ID').put((request,response)=>{
    dboperations.updateComments(request.params.ID).then(result => {
        response.json(result[0]);
        console.log(result[0]);
    })
})

var port = process.env.PORT || 5000;
app.listen(port);
console.log('Customer Order API is running at ' + port);

dboperations.getcustomerOrders().then(result => {
    console.log(result);
})

dboperations.getallcustomerOrders().then(result => {
    console.log(result);
})

dboperations.updateComments().then(result => {
    console.log(result);
})

EmailFaxDetails.js

import React, { useState,useEffect } from 'react'
import FetchOrderDetails from './FetchOrderDetails';
import axios from 'axios'
import '../App.css';

const EmailFaxDetails = () => {

    const [orderNumber, setOrderNumber] = useState('');
    const [id, setId] = useState([]);
    const [isShown, setIsShown] = useState(false);

    const url = `http://localhost:5000/api/customerOrder/${orderNumber}`
      useEffect(() => {
        axios.get(url)
        .then(response => {
          setId(response.data)
          console.log(response.data)
        })
        .catch((err) => console.log(err));
      }, [url]);

  const handleChange = event => {
    setOrderNumber(event.target.value);
    console.log(event.target.value);
  };

  const handleClick = event => {
    event.preventDefault();
    setIsShown(true);
    console.log(orderNumber);
  }

    return(
        <div>
            <br></br>
            <br></br>
            Order Number: <input placeholder="Order Number" type="text" id="message" name="message" onChange={handleChange} value={orderNumber} autoComplete="off" />
                {id.map((idnum) => (
                    <div key={idnum.ID}>
                    {isShown && <FetchOrderDetails ord_no={orderNumber} cmt={idnum.cmt} id={idnum.ID}/>}
                    </div>
                ))} 
            <button onClick={handleClick}>Search</button>
        </div>
    )
}

export default EmailFaxDetails;

问题排查与修复方案

核心问题分析

  1. 前端请求时机错误:
    组件挂载时orderNumber为空字符串,useEffect依赖url会自动发起请求http://localhost:5000/api/customerOrder/,虽然HTTP方法是GET,但服务端启动时的无参数函数调用已导致内部错误。

  2. 服务端updateComments函数致命缺陷:

    • 未接收req、res参数却直接使用,导致变量未定义抛出错误;
    • 启动时被无参数调用,直接触发内部报错。
  3. 服务端接口无错误捕获:
    getcustomerOrders等函数捕获错误后仅打印,未向上抛出,导致路由层无法处理异常,最终返回500错误。

修复步骤

1. 修复前端请求逻辑

改为点击搜索按钮后才发起请求,避免空参数请求:

import React, { useState } from 'react'
import FetchOrderDetails from './FetchOrderDetails';
import axios from 'axios'
import '../App.css';

const EmailFaxDetails = () => {
    const [orderNumber, setOrderNumber] = useState('');
    const [id, setId] = useState([]);
    const [isShown, setIsShown] = useState(false);

    const fetchOrderData = async () => {
        if (!orderNumber.trim()) return;
        try {
            const url = `http://localhost:5000/api/customerOrder/${orderNumber}`;
            const response = await axios.get(url);
            setId(response.data);
            setIsShown(true);
        } catch (err) {
            console.log(err);
            setIsShown(false);
        }
    };

    const handleChange = event => {
        setOrderNumber(event.target.value);
    };

    const handleClick = event => {
        event.preventDefault();
        fetchOrderData();
    };

    return(
        <div>
            <br></br>
            <br></br>
            Order Number: 
            <input 
                placeholder="Order Number" 
                type="text" 
                id="message" 
                name="message" 
                onChange={handleChange} 
                value={orderNumber} 
                autoComplete="off" 
            />
            {isShown && id.map((idnum) => (
                <div key={idnum.ID}>
                    <FetchOrderDetails ord_no={orderNumber} cmt={idnum.cmt} id={idnum.ID}/>
                </div>
            ))} 
            <button onClick={handleClick}>Search</button>
        </div>
    )
}

export default EmailFaxDetails;

2. 修复服务端updateComments函数

补充参数并修正内部逻辑:

async function updateComments(ID, req, res) {
    try {
        let pool = await sql.connect(config);
        let orders = await pool.request()
            .input('ID', sql.NChar, ID)
            .query(`SELECT cmt FROM [100].[dbo].[OELINCMT_SQL] WHERE ID = @ID`);

        let order = orders.recordset.length ? orders.recordset[0] : null;
        if (order) {
            await pool.request()
                .input('ID', sql.NChar, ID)
                .input('cmt', sql.NChar, req.body.cmt)
                .query(`UPDATE [100].[dbo].[OELINCMT_SQL] SET cmt = @cmt WHERE ID = @ID;`);

            order = { ...order, ...req.body };
            res.json(order);
        } else {
            res.status(404).json({ message: 'Record not found' });
        }
    } catch (error) {
        console.log(error);
        res.status(500).json({ error: error.message });
    }
}

3. 修复服务端路由与启动错误

删除无参数调用,添加错误捕获,修正PUT路由调用:

var dboperations = require('./dboperations');
var express = require('express');
var bodyParser = require('body-parser');
var cors = require('cors');
var app = express();
var router = express.Router();

app.use(bodyParser.urlencoded({ extended: true}));
app.use(bodyParser.json());
app.use(cors());
app.use('/api', router);

router.use((request,response,next)=> {
    console.log('middleware');
    next();
})

router.route('/customerOrder').get((request,response)=>{
    dboperations.getallcustomerOrders()
        .then(result => response.json(result[0]))
        .catch(err => response.status(500).json({ error: err.message }))
})

router.route('/customerOrder/:orderNumber').get((request,response)=>{
    dboperations.getcustomerOrders(request.params.orderNumber)
        .then(result => response.json(result[0]))
        .catch(err => response.status(500).json({ error: err.message }))
})

router.route('/customerOrder/:ID').put((request,response)=>{
    dboperations.updateComments(request.params.ID, request, response)
        .catch(err => response.status(500).json({ error: err.message }))
})

var port = process.env.PORT || 5000;
app.listen(port);
console.log('Customer Order API is running at ' + port);

4. 补充服务端函数错误抛出

修改getallcustomerOrders和getcustomerOrders,让错误能被路由层捕获:

async function getallcustomerOrders(){
    try{
        let pool = await sql.connect(config);
        let orders = await pool.request()
            .query("SELECT * FROM [100].[dbo].[OELINCMT_SQL] order by ID desc");
        return orders.recordsets;
    }
    catch (error){
        console.log(error);
        throw error;
    }
}

async function getcustomerOrders(orderNumber) {
    try {
        let pool = await sql.connect(config);
        let orders = await pool.request()
            .input('input_parameter', sql.NChar, orderNumber)
            .query("SELECT ID,cmt FROM [100].[dbo].[OELINCMT_SQL] where LTRIM(ord_no) = LTRIM(@input_parameter)");
        return orders.recordsets;
    }
    catch (error) {
        console.log(error);
        throw error;
    }
}

内容的提问来源于stack exchange,提问作者Glenn94

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 02:30:50