Express app.post被多次调用 [英] Express app.post getting called multiple times

查看:128
本文介绍了Express app.post被多次调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在构建一个youtube视频转换应用程序,该应用程序使用youtube-dl流式传输youtube视频并将其保存,直到我尝试流式传输一个小时以上的视频之前,一切都运行良好.当任务完成的时间介于50%-100%之间或40-80秒之间时,就是重新运行整个代码块,导致同时发生多个流.因此,在等待管道完成时,永远不会发送响应.添加next();流功能外部允许转换完成而不会中断代码块或重新运行,但是在尝试发送响应时导致以下错误:

I have been building a youtube video conversion app which streams youtube videos using youtube-dl and saves them, everything was working fine until I attempted to stream a video that was over an hour long. When the task was anywhere between 50% - 100% complete or 40-80seconds in, would be when the entire block of code would get re-run resulting in multiple simultaneous streams occurring. The response can therefor never get sent as it waits for the pipe to finish. Adding next(); outside the stream function allowed the conversion to complete with out any interruption or reruns of the code block, however it resulted in the following error when attempting to send the response:

throw new Error('Can\'t set headers after they are sent.');

这是有问题的Node.js代码块:

This is the Node.js code block in question:

app.post('/convert/', function (req, res, next){
  var url = 'http://www.youtube.com/'+req.body.url;
  var quality = req.body.quality;
  var socketId = req.body.socketId;


stream = youtubedl(url, 
  ['-f ' + quality],

  // // Additional options can be given for calling `child_process.execFile()`. 
  { cwd: __dirname });

stream.on('info', function(info) {

  console.log('Download started');
  console.log('filename: ' + info._filename);
  console.log('size: ' + info.size);
  console.log('format: ' + info.format);

  var fileName = info._filename;
  var videoId = info.id;
  var videoTitle = info.title;
  videoTitle = videoTitle.replace(/[^a-zA-Z0-9\s]/g, '');
  console.log(videoTitle);

  var mp4 = 'downloads/'+videoTitle+'-'+info.format_id+'.mp4';
  fs.writeFile(mp4, "file", function(err) {
      if(err) {
          return console.log(err);
      }

    console.log("The file was saved!");
    var stat = fs.statSync(mp4);
    var str = progress({
      length: info.size,
      time: 100
    });

    str.on('progress', function(progress) {
      io.to(global.socketid).emit('progressVideo',{progress: progress.percentage});
      console.log(info.size);
      console.log(progress.transferred);
      console.log(progress.percentage);
      console.log(progress.remaining);
    });

    var pipe = stream.pipe(str).pipe(fs.createWriteStream(mp4));

    pipe.on('finish', function () {
      console.log("stream finished.");
      res.json(videoTitle+'-'+info.format_id+'.mp4');
    });
  });
 });
 // next();
});

由一些Angular代码调用.

Called by some Angular code.

// Sends youtube link to backend
$scope.getVideo = function(youtubeLink, resolution){
    var cleanedLink = youtubeLink.substring(24);
    var url = {url: cleanedLink, quality: resolution};
    $http.post('/convert/', url).success(function (response){
      // Do some stuff
    });
}

对于为什么为什么要运行一次又一次又一次的运行感到困惑,我慢慢删除了越来越多的代码,直到剩下这个简单的测试为止.

Confused as to why it was getting run more then once, I slowly removed more and more code until I was left with this simple test.

app.post('/convert/', function (req, res, next){
  console.log('hello!');
});

这是由ng-click事件调用的,在等待一分钟左右后,控制台还打印了两个,然后打印了三个hello!语句.我完全不知道为什么会这样.如果有人能为我提供一些启示,将不胜感激.

Which was called by an ng-click event and after waiting a minute or so the console also printed out two and then three hello! statements. I am completely lost as to why this happens. If anyone could shed some light on this for me it would be greatly appreciated.

推荐答案

因此,在走到非常基本的发布路线并注销了一些文本但未返回响应之后,我得出了这个问题与节点有关的结论.我决定记录一下console.log语句之间的时间长度,结果是每2分钟一次.有了这个,我能够发现如果未将响应发送回客户端,则该节点的默认超时为2分钟.

So after just getting down to a very basic post route and logging out some text but not returning a response, I came to the conclusion the issue resides with node. I decided to record the length of time between the console.log statements which turned out to be every 2 minutes. With this I was able to find out that node has a default timeout of 2 minutes if a response is not sent back to the client.

我可以使用以下代码将响应设置为永不超时:

I was able to set the response to never timeout with the following code:

res.connection.setTimeout(0);

我希望这对需要长时间保持连接以进行文件转换/传输等的其他人有帮助...

I hope this helps anyone else that needs to hold connections for large periods of times for file conversions/transfers etc...

这篇关于Express app.post被多次调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆