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

NodeJS服务端函数无法被HTML调用,文件搜索功能实现遇阻

问题描述

我想要创建一个带有基础过滤搜索列表的网页,该列表需搜索txt文件中的数据并返回包含目标内容的文件名。我尝试通过Node.js编写JavaScript文件,在服务端用readFileSync读取txt文件数据,再将结果返回给客户端HTML,但运行时HTML找不到对应的函数,推测是客户端与服务端的通信逻辑有问题。

原服务端文件function.js:

const http = require('http');
const fs = require('fs');
var index = fs.readFileSync('functioncall.html');

//The function run by the HTML file
function myFunction() {
    var nameArray = ['./File1.txt', './File2.txt'], resultArray = [], input, filter, ul, li, i, nameValue, fileText;

    input = document.getElementById("myInput");
    filter = input.value.toUpperCase();
    ul = document.getElementById("myUL");
    li = ul.getElementsByTagName("li");  
    
    //Run through the file names and check if the requested text exists in the file, then push the name into an array if successful, else null
    For (i = 0; i < nameArray.length; i++) {
        nameValue = nameArray[i];
        
        fileText = fs.readFileSync(nameValue, {encoding:'utf8', flag:'r'}).value.toUpperCase();

        if (fileText.indexOf(filter) >= 0) { 
          resultArray.push(nameValue);
        }
        else{
          resultArray.push(null);
        }
    }
    //If the search function gets a hit, display the name in the HTML file
    for (i = 0; i < li.length; i++) {
        if (resultArray[i] != null) {
          li[i].style.display = "";
        } else {
          li[i].style.display = "none";
        }
   }
}


http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/html'});
    res.end(index);
}).listen(3000);

原HTML文件functioncall.html:

<!DOCTYPE html>
<html>
<head>
<script type = "text/javascript" src="function.js"></script>  
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
* {
  box-sizing: border-box;
}

#myInput {
  background-image: url('/css/searchicon.png');
  background-position: 10px 12px;
  background-repeat: no-repeat;
  width: 100%;
  font-size: 16px;
  padding: 12px 20px 12px 40px;
  border: 1px solid #ddd;
  margin-bottom: 12px;
}

#myUL {
  list-style-type: none;
  padding: 0;
  margin: 0;
}

#myUL li a {
  border: 1px solid #ddd;
  margin-top: -1px; /* Prevent double borders */
  background-color: #f6f6f6;
  padding: 12px;
  text-decoration: none;
  font-size: 18px;
  color: black;
  display: block
}

#myUL li a:hover:not(.header) {
  background-color: #eee;
}
</style>
</head>
<body>

<h2>File Search</h2>

<input type="text" id="myInput" onkeyup="myFunction()" placeholder="Search for text.." title="Type in text">

<ul id="myUL">
  <li><a href="#">File1.txt</a></li>
  <li><a href="#">File2.txt</a></li>
</ul>

</body>
</html>
错误原因
  1. 代码混写问题:把服务端Node.js专属代码(fs、http模块)和客户端DOM操作代码放在同一个文件里。浏览器无法识别Node.js模块,加载function.js时会直接报错,导致myFunction无法被找到。
  2. 服务端函数未暴露:myFunction定义在服务端代码中,不会被发送到客户端,客户端自然无法调用。
  3. 语法错误:代码里的For应该是小写for;fs.readFileSync返回的是字符串,不需要.value属性。
解决方案

拆分服务端和客户端代码,通过HTTP接口实现前后端通信:

1. 服务端代码(server.js)

负责提供HTML页面和处理搜索请求:

const http = require('http');
const fs = require('fs');
const path = require('path');

const PORT = 3000;
const FILES = ['./File1.txt', './File2.txt'];

// 创建服务器
const server = http.createServer((req, res) => {
    // 处理根路径请求,返回HTML页面
    if (req.url === '/') {
        fs.readFile(path.join(__dirname, 'functioncall.html'), (err, data) => {
            if (err) {
                res.writeHead(500, {'Content-Type': 'text/plain'});
                res.end('Internal Server Error');
                return;
            }
            res.writeHead(200, {'Content-Type': 'text/html'});
            res.end(data);
        });
    } 
    // 处理搜索请求
    else if (req.url.startsWith('/search')) {
        // 解析查询参数
        const query = new URL(req.url, `http://localhost:${PORT}`).searchParams.get('q');
        if (!query) {
            res.writeHead(400, {'Content-Type': 'application/json'});
            res.end(JSON.stringify({matches: FILES}));
            return;
        }
        const filter = query.toUpperCase();
        const matches = [];

        // 遍历文件,检查内容是否匹配
        for (const filePath of FILES) {
            try {
                const fileContent = fs.readFileSync(filePath, {encoding: 'utf8'}).toUpperCase();
                if (fileContent.includes(filter)) {
                    matches.push(filePath);
                }
            } catch (err) {
                console.error(`读取文件失败:${filePath}`, err);
            }
        }

        res.writeHead(200, {'Content-Type': 'application/json'});
        res.end(JSON.stringify({matches}));
    }
    // 处理客户端JS文件请求
    else if (req.url === '/client.js') {
        fs.readFile(path.join(__dirname, 'client.js'), (err, data) => {
            if (err) {
                res.writeHead(500, {'Content-Type': 'text/plain'});
                res.end('Internal Server Error');
                return;
            }
            res.writeHead(200, {'Content-Type': 'application/javascript'});
            res.end(data);
        });
    }
    // 404处理
    else {
        res.writeHead(404, {'Content-Type': 'text/plain'});
        res.end('Not Found');
    }
});

server.listen(PORT, () => {
    console.log(`服务器运行在 http://localhost:${PORT}`);
});

2. 客户端JS代码(client.js)

负责页面交互和调用服务端API:

async function myFunction() {
    const input = document.getElementById("myInput");
    const filter = input.value.trim();
    const ul = document.getElementById("myUL");
    const items = ul.querySelectorAll("li");

    // 调用服务端搜索接口
    const response = await fetch(`/search?q=${encodeURIComponent(filter)}`);
    const data = await response.json();
    const matchedFiles = data.matches;

    // 更新列表显示
    items.forEach(item => {
        const fileName = item.querySelector('a').textContent;
        // 检查当前文件名是否在匹配列表中
        const isMatched = matchedFiles.some(filePath => filePath.includes(fileName));
        item.style.display = isMatched ? "" : "none";
    });
}

3. 修改后的HTML文件(functioncall.html)

引入客户端专属的JS文件:

<!DOCTYPE html>
<html>
<head>
<script type = "text/javascript" src="client.js"></script>  
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
* {
  box-sizing: border-box;
}

#myInput {
  background-image: url('/css/searchicon.png');
  background-position: 10px 12px;
  background-repeat: no-repeat;
  width: 100%;
  font-size: 16px;
  padding: 12px 20px 12px 40px;
  border: 1px solid #ddd;
  margin-bottom: 12px;
}

#myUL {
  list-style-type: none;
  padding: 0;
  margin: 0;
}

#myUL li a {
  border: 1px solid #ddd;
  margin-top: -1px; /* Prevent double borders */
  background-color: #f6f6f6;
  padding: 12px;
  text-decoration: none;
  font-size: 18px;
  color: black;
  display: block
}

#myUL li a:hover:not(.header) {
  background-color: #eee;
}
</style>
</head>
<body>

<h2>File Search</h2>

<input type="text" id="myInput" onkeyup="myFunction()" placeholder="Search for text.." title="Type in text">

<ul id="myUL">
  <li><a href="#">File1.txt</a></li>
  <li><a href="#">File2.txt</a></li>
</ul>

</body>
</html>
使用步骤
  1. 创建File1.txt和File2.txt,写入测试内容;
  2. 将上述三个文件放在同一目录下;
  3. 运行node server.js启动服务;
  4. 访问http://localhost:3000,在输入框中输入文本即可搜索匹配的文件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 11:01:08