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

Express.js中API请求404错误排查及优化实现咨询

问题分析与优化方案

首先咱们先解决你遇到的404错误,再一步步优化整个实现流程:

1. 404错误的核心原因:请求路径不匹配

你提到的测试URL是http://......../books/keyword=intro,这里犯了一个基础错误:GET请求的查询参数格式是?key=value,而非/key=value。正确的请求URL应该是http://......../books?keyword=intro。

你的Express路由定义的是app.get('/books', ...),当请求/books/keyword=intro时,Express找不到对应的路由规则,自然返回404。不过看你的前端代码里的theUrl是'books?keyword=' + searchTerm,这个写法是对的,应该是你手动测试时写错了路径~

2. 后端查询逻辑的关键优化(别全表查询后再过滤!)

你当前的后端逻辑是先把books表的所有数据查出来,再用JS循环匹配关键词,这在数据量小时没问题,但数据量大时会极度低效,还浪费数据库资源。正确的做法是直接把查询条件写到SQL语句里,让数据库帮你完成过滤:

app.get('/books', function(req, res){ 
  const { keyword } = req.query;
  // 注意:必须用参数化查询防止SQL注入!
  connection.query('SELECT * from books WHERE title LIKE ?', [`%${keyword}%`], function (error, results, fields) { 
    if (error) {
      console.error(error);
      return res.status(500).json({ error: '数据库查询失败' });
    }
    // 处理无匹配结果的情况
    if (results.length === 0) {
      return res.status(404).json({ message: '未找到匹配的书籍' });
    }
    // 返回JSON格式的结果,符合API规范
    res.json(results);
  }); 
});

⚠️ 重要提醒:绝对不要直接把用户输入拼到SQL语句里,这会导致严重的SQL注入攻击!上面用的参数化查询(?作为占位符),会由数据库连接库自动处理转义,保证查询安全。

3. 前端代码的修复与体验优化

你的前端代码有几个小问题需要调整,同时可以提升用户体验:

  • 重复的id="search":输入框和结果div用了同一个id,会导致DOM选择出错,把结果div的id改成search-result;
  • XHR的语法错误:if (xhttp.readyState == XMLHttpRequest.DONE);多了个分号,会导致后续代码无论请求状态如何都会执行,还要增加status === 200的判断确保请求成功;
  • 增加错误处理:比如网络错误、服务器返回异常状态码的情况;
  • 增加回车触发搜索的功能,提升用户体验。

优化后的前端代码:

<!DOCTYPE html>
<html>
<head>
  <title>书籍搜索</title>
</head> 
<body> 
  <div id="data"> 
    <input type="button" id="button" value="搜索书籍"/> 
    <input type="text" id="search-input" placeholder="输入书名关键词"> 
  </div> 
  <div id="search-result"></div> 
  <script> 
    document.getElementById('button').addEventListener('click', getUserInput);
    // 增加回车触发搜索
    document.getElementById('search-input').addEventListener('keypress', function(e) {
      if (e.key === 'Enter') getUserInput();
    });

    function getUserInput(event){ 
      const userInput = document.getElementById("search-input").value.trim();
      if(userInput !== ""){ 
        httpGetAsync(userInput); 
      } else {
        alert('请输入搜索关键词');
      }
    } 

    function httpGetAsync(searchTerm){ 
      // 对搜索关键词编码,处理特殊字符
      const theUrl = 'books?keyword=' + encodeURIComponent(searchTerm);
      const xhttp = new XMLHttpRequest(); 
      xhttp.open("GET", theUrl, true); 
      xhttp.send(); 
      xhttp.onreadystatechange = function() { 
        if (xhttp.readyState === XMLHttpRequest.DONE) {
          if (xhttp.status === 200) {
            try {
              const results = JSON.parse(xhttp.response);
              displayResults(results);
            } catch (e) {
              console.error('解析响应失败', e);
              document.getElementById('search-result').textContent = '数据解析错误';
            }
          } else if (xhttp.status === 404) {
            document.getElementById('search-result').textContent = '未找到匹配的书籍';
          } else {
            document.getElementById('search-result').textContent = `请求失败,状态码:${xhttp.status}`;
          }
        }
      };
    }

    // 渲染搜索结果到页面
    function displayResults(results) {
      const resultDiv = document.getElementById('search-result');
      resultDiv.innerHTML = '';
      if (results.length === 0) {
        resultDiv.textContent = '未找到匹配的书籍';
        return;
      }
      const ul = document.createElement('ul');
      results.forEach(book => {
        const li = document.createElement('li');
        // 根据你的数据库表结构调整显示字段
        li.textContent = `${book.title} - ${book.author || '未知作者'}`;
        ul.appendChild(li);
      });
      resultDiv.appendChild(ul);
    }
  </script> 
</body>
</html>

4. 关于keyword=intro格式的疑问

keyword=intro是GET请求查询参数的标准格式,完全没问题!Express会自动把URL中的查询参数解析到req.query对象里,所以你用const { keyword } = req.query;的写法是完全正确的。

按照上面的方案调整后,应该就能解决404问题,同时让整个搜索功能更高效、安全、易用啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:32:34