javascript - 多次运行函数返回“错误:发送后无法设置标头”
问题描述
程序运行正常,直到我再次尝试使用该函数并返回错误: Can't set headers after they are sent。
我正在创建此应用程序以熟悉 nodejs 和 javascript,并且我一直在阅读有关该错误的信息,并且在对请求发送多个响应时似乎是一个问题。我在知道这一点之前就开始使用res.setHeader,但我读到res.header可以避免这个问题,它没有解决它,但我保留了它。
HTML:
<!doctype html>
<head>
<link rel="stylesheet" type="text/css" href="youtube2music.css">
<title>
Youtube2Music
</title>
</head>
<body>
<div id="cabeza">
<h1>
Youtube 2 Music
</h1>
<p>
just paste your link below and download your song.
</p>
</div>
<div id="down-part">
<input id="myUrl" class='myUrl-input'>
</input>
<button type="button" class="download_button">
Download
</button>
</div>
</body>
<script src='youtube2music.js'></script>
</html>
Javascript:
var urlinput = document.querySelector('.myUrl-input'); // gets url inputbox
var button = document.querySelector('.download_button'); // gets download button
button.addEventListener('click', () => {
console.log(urlinput.value); // prints in console the url
sendUrl(urlinput.value); // sends url to function to start the request
});
// function to make requst
function sendUrl(URL){
window.location.href = `http://localhost:4000/?URL=${URL}`; // makes the video request to nodejs server
}
index.js <节点文件:
var eventEmitter = new events.EventEmitter();
var sfn;
appi.use(cors());
const {app, BrowserWindow} = require('electron')
function createWindow(){
let win = new BrowserWindow({width:800, height:600});
win.loadFile('index.html');
}
app.on('ready', createWindow)
appi.listen(4000, () => {
console.log('server at port 4000');
});
appi.get('/',(req,res)=>{
var URL = req.query.URL;
ytdl.getInfo(URL, function(err,info){
if(err) throw err;
var songTitle = info.title;
sfn = filenamify(songTitle);
eventEmitter.emit('name_ready');
});
var startDownload = function(){
let stream = ytdl(URL, {
quality: 'highestaudio',
});
res.header('Content-Disposition', 'attachment; filename=' + sfn + '.mp3');
res.header('Content-type', 'audio/mpeg');
proc = new ffmpeg({source: stream})
proc.withAudioCodec('libmp3lame').toFormat('mp3').output(res).run();
}
eventEmitter.on('name_ready', startDownload);
})
因为它适用于第一个输入但要求另一个输出导致错误,为什么它真的返回这个错误以及如何避免它?
解决方案
您当前的设置存在几个问题:
- 尽量不要在 HTTP 请求中使用事件发射器来发送事件信号,它不是为此而设计的。
- 对于 HTTP 请求,尽量不要对请求过程中收到的数据使用全局变量,当两个请求同时进来时,可能会混淆并发送错误的数据。
appi.listen(4000, () => {
console.log('server at port 4000');
});
appi.get('/', (req,res)=> {
const { URL } = req.query;
ytdl.getInfo(URL, (err,info) => {
if(err) throw err;
const songTitle = info.title;
const sfn = filenamify(songTitle);
let stream = ytdl(URL, {
quality: 'highestaudio',
});
res.set('Content-Disposition', 'attachment; filename=' + sfn + '.mp3');
res.set('Content-type', 'audio/mpeg');
const proc = new ffmpeg({source: stream})
proc.withAudioCodec('libmp3lame').toFormat('mp3').output(res).run();
});
})
推荐阅读
- javascript - 问题检查元素是否在 javascript 中处于“活动状态”
- html - 不同列中第一个 div 的高度相等(引导程序 4)
- arrays - 在具有 React 状态的 div 网格中跟踪选定的 div
- python - 使用 django 形式执行一些计算。哪个框架?
- php - 模型观察者:restored() 和 restore()
- html - 如何让图像和其他元素保持原位
- swift - 这个 RxAlamofire 源代码中的实际 API 调用在哪里?
- azure - 整个字段的 Azure 搜索筛选器
- hadoop - 无法将点/检查点 flink 状态保存到 AWS S3 存储桶
- python - TypeError:需要一个类似字节的对象,而不是“str”,但类型显示字节