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>
错误原因
- 代码混写问题:把服务端Node.js专属代码(
fs、http模块)和客户端DOM操作代码放在同一个文件里。浏览器无法识别Node.js模块,加载function.js时会直接报错,导致myFunction无法被找到。 - 服务端函数未暴露:
myFunction定义在服务端代码中,不会被发送到客户端,客户端自然无法调用。 - 语法错误:代码里的
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>
使用步骤
- 创建
File1.txt和File2.txt,写入测试内容; - 将上述三个文件放在同一目录下;
- 运行
node server.js启动服务; - 访问
http://localhost:3000,在输入框中输入文本即可搜索匹配的文件。
内容的提问来源于stack exchange,提问作者pshapes1225
相关产品推荐
相关产品推荐

