Node.js实现前端终端实时显示sass --watch输出的问题
问题:前端模拟终端实时展示
sass --watch输出,res.render仅能调用一次如何实现多次返回数据 我希望在前端模拟终端,实时展示sass --watch的输出,但res.render仅能调用一次,请问有什么方法可以实现多次返回数据?
后端代码(server.js)
app.get('/sass', function (req, res) { path1 = req.query.chemin; path2 = req.query.chemin; const ls = spawn('sass', ['--watch path1 path2'], { shell: true }); ls.stdout.on('data', (data) => { console.log(ls.pid); message = JSON.stringify(`stdout: ${data}`); res.render('index', { messagee: message, path: firstpath }); }); });
前端代码(index.ejs)
<div id="terminal"> <%= messagee %> </div>
项目结构
server.js - views -- index.ejs - public -- css -- js -- img
解决方案
HTTP请求是一次性响应模型,res.render只能完成单次页面渲染,要实现实时数据推送,推荐使用Server-Sent Events(SSE)——它适合这种单向的日志/输出推送场景,实现步骤如下:
1. 后端改造:用SSE推送sass --watch输出
修改接口逻辑,不再调用res.render,而是返回持续的SSE数据流:
app.get('/sass-stream', function (req, res) { // 设置SSE响应头,保持连接存活 res.setHeader('Content-Type', 'text/event-stream'); res.setHeader('Cache-Control', 'no-cache'); res.setHeader('Connection', 'keep-alive'); const path1 = req.query.chemin; const path2 = req.query.chemin; // 注意:此处path1和path2取值相同,若为笔误请修正实际路径 // 启动sass监听进程(拆分参数避免shell解析问题) const ls = spawn('sass', [`--watch`, path1, path2], { shell: true }); // 监听标准输出,推送给前端 ls.stdout.on('data', (data) => { const msg = `stdout: ${data.toString().trim()}`; // 按SSE格式写入数据:data: 内容\n\n res.write(`data: ${JSON.stringify(msg)}\n\n`); }); // 监听错误输出 ls.stderr.on('data', (data) => { const errMsg = `stderr: ${data.toString().trim()}`; res.write(`data: ${JSON.stringify(errMsg)}\n\n`); }); // 进程退出时关闭连接 ls.on('close', (code) => { res.write(`data: ${JSON.stringify(`sass进程已退出,退出码:${code}`)}\n\n`); res.end(); }); // 前端断开连接时,杀死sass进程避免资源浪费 req.on('close', () => { ls.kill(); }); });
2. 前端改造:接收SSE并更新终端内容
修改index.ejs,添加JS代码监听SSE流,实时追加输出到终端:
<div id="terminal" style="background: #1e1e1e; color: #d4d4d4; padding: 12px; font-family: monospace; min-height: 240px; overflow-y: auto;"></div> <script> const terminal = document.getElementById('terminal'); // 替换成实际的路径参数,或从页面渲染数据中获取 const targetPath = '<%= path %>'; // 建立SSE连接 const eventSource = new EventSource(`/sass-stream?chemin=${encodeURIComponent(targetPath)}`); // 接收推送的消息并更新终端 eventSource.onmessage = function(e) { const message = JSON.parse(e.data); terminal.innerHTML += message + '<br>'; // 自动滚动到底部 terminal.scrollTop = terminal.scrollHeight; }; // 处理连接错误 eventSource.onerror = function(e) { terminal.innerHTML += '连接异常,已断开<br>'; eventSource.close(); }; </script>
3. 补充初始页面路由
保留一个基础路由用于渲染初始页面:
app.get('/', function(req, res) { res.render('index', { path: req.query.chemin || '' }); });
用户访问页面后,前端会自动建立SSE连接,后端将sass --watch的实时输出持续推送到前端终端。
内容的提问来源于stack exchange,提问作者William Gaonarch
相关产品推荐
相关产品推荐

