React JS中实现加载组件直至Python降噪脚本执行完成
解决方案:添加加载状态直到音频降噪完成
前端(React)修改
1. 主组件中管理加载状态
在你的React主组件中新增isLoading状态,用来控制加载组件的显示与隐藏:
import { useState } from 'react'; import DenoiseModal from './DenoiseModal'; function AudioDenoiseApp() { const [isLoading, setIsLoading] = useState(false); const handleDenoise = async (audioFile) => { setIsLoading(true); try { const formData = new FormData(); formData.append('audio', audioFile); const response = await fetch('/api/denoise', { method: 'POST', body: formData, }); if (!response.ok) throw new Error('降噪处理失败'); // 处理返回的降噪音频(示例:生成下载链接) const blob = await response.blob(); const downloadUrl = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = downloadUrl; a.download = `denoised_${audioFile.name}`; a.click(); URL.revokeObjectURL(downloadUrl); } catch (error) { console.error('处理出错:', error); // 这里可以添加错误提示弹窗 } finally { setIsLoading(false); } }; return ( <div className="app-container"> {/* 加载遮罩层,处理中时显示 */} {isLoading && ( <div className="loading-overlay"> <div className="loading-content"> <div className="spinner"></div> <p>正在降噪处理,请稍候...</p> </div> </div> )} <DenoiseModal onDenoise={handleDenoise} isLoading={isLoading} /> </div> ); } export default AudioDenoiseApp;
2. 调整DenoiseModal组件
给按钮添加禁用状态,避免重复提交,同时修改按钮文本提示:
import { useState } from 'react'; function DenoiseModal({ onDenoise, isLoading }) { const [selectedFile, setSelectedFile] = useState(null); const handleFileChange = (e) => { setSelectedFile(e.target.files[0]); }; const handleSubmit = () => { if (selectedFile) { onDenoise(selectedFile); } }; return ( <div className="modal"> <h3>上传音频文件</h3> <input type="file" accept="audio/*" onChange={handleFileChange} disabled={isLoading} /> <button onClick={handleSubmit} disabled={isLoading || !selectedFile} className="denoise-btn" > {isLoading ? '处理中...' : '开始降噪'} </button> </div> ); } export default DenoiseModal;
后端(Express)修改
确保服务器在Python脚本完全执行完成、结果文件写入完毕后再返回响应,保证前端加载状态与处理进度同步:
const express = require('express'); const { spawn } = require('child_process'); const fs = require('fs'); const path = require('path'); const multer = require('multer'); const app = express(); // 配置文件上传目录 const upload = multer({ dest: path.join(__dirname, 'uploaded_audio') }); // 确保降噪输出目录存在 const denoisedDir = path.join(__dirname, 'denoised_audio'); if (!fs.existsSync(denoisedDir)) fs.mkdirSync(denoisedDir); app.post('/api/denoise', upload.single('audio'), (req, res) => { const inputFile = req.file; const outputFileName = `denoised_${inputFile.originalname}`; const outputPath = path.join(denoisedDir, outputFileName); // 执行Python降噪脚本,传入输入/输出路径参数 const pythonProcess = spawn('python', [ path.join(__dirname, 'your_denoise_script.py'), inputFile.path, outputPath ]); // 监听脚本执行结束事件 pythonProcess.on('exit', (code) => { if (code === 0) { // 脚本执行成功,返回降噪文件给前端 res.download(outputPath, outputFileName, (err) => { if (err) { res.status(500).send('文件返回失败'); } // 清理临时文件(可选) fs.unlinkSync(inputFile.path); fs.unlinkSync(outputPath); }); } else { res.status(500).send('降噪脚本执行失败'); // 清理上传的原始文件 fs.unlinkSync(inputFile.path); } }); // 捕获Python脚本的错误输出 pythonProcess.stderr.on('data', (data) => { console.error(`Python脚本错误日志:${data.toString()}`); }); }); const PORT = 3001; app.listen(PORT, () => { console.log(`服务器运行在 http://localhost:${PORT}`); });
关键注意点
- 前端通过
finally块确保无论成功还是失败,加载状态都会关闭,避免一直显示加载。 - 后端依赖Python脚本的
exit事件判断处理完成,确保结果文件已经完全写入磁盘后再返回给前端。 - 如果脚本执行时间过长,可在前端请求中设置超时(比如Axios的
timeout: 300000,即5分钟),避免请求被浏览器中断。 - 确保服务器目录(
uploaded_audio、denoised_audio)有读写权限,避免文件操作失败。
内容的提问来源于stack exchange,提问作者Steven
相关产品推荐
相关产品推荐

