我的印象是,虽然Node JS是单线程的,但文件io是异步的。
var express = require('express');
var http = require('http');
var fs = require('fs');
var app = express();
var server = app.listen(1337, function() {
console.log('Listening on port %d', server.address().port);
});
app.get('/home', function(req, res){
console.log("/home")
res.sendFile('C:\\Users\\Owner\\AppData\\Roaming\\npm\\test.html');
//var file = fs.createReadStream('C:/Users/Owner/AppData/Roaming/npm/test.html');
//file.on("open", function(){
// file.pipe(res);
//});
});
app.get('/home2', function(req, res){
console.log("/home2")
res.sendFile('C:\\Users\\Owner\\AppData\\Roaming\\npm\\test2.html');
//var file = fs.createReadStream('C:/Users/Owner/AppData/Roaming/npm/test.html');
//file.on("open", function(){
// file.pipe(res);
//});
});
app.get('/music', function(req, res){
console.log("/music")
//res.sendFile('C:\\Users\\Owner\\AppData\\Roaming\\npm\\01 Give Life Back To Music.mp4');
var readStream = fs.createReadStream('C:\\Users\\Owner\\AppData\\Roaming\\npm\\01 Give Life Back To Music.mp4');
console.log("/afterRead");
readStream.on('data', function(data) {
var flushed = res.write(data);
// Pause the read stream when the write stream gets saturated
console.log( 'streaming data' );
if(!flushed){
readStream.pause();
}
});
res.on('drain', function() {
// Resume the read stream when the write stream gets hungry
readStream.resume();
});
readStream.on('end', function () {
res.end();
console.log('end');
});
});
app.get('/music2', function(req, res){
console.log("/music2")
//res.sendFile('C:\\Users\\Owner\\AppData\\Roaming\\npm\\01 Give Life Back To Music.mp4');
var readStream = fs.createReadStream('C:\\Users\\Owner\\AppData\\Roaming\\npm\\01 Give Life Back To Music.mp4');
console.log("/afterRead");
readStream.on('data', function(data) {
var flushed = res.write(data);
// Pause the read stream when the write stream gets saturated
console.log( 'streaming data' );
if(!flushed){
readStream.pause();
}
});
res.on('drain', function() {
// Resume the read stream when the write stream gets hungry
readStream.resume();
});
readStream.on('end', function () {
res.end();
console.log('end');
});
});
上面是服务器代码,这是我的HTML:
<html>
<script>
</script>
<body>
<video width="320" height="240" controls>
<source src="http://localhost:1337/music1" type="video/mp4">
Your browser does not support the video tag.
</video>
</body>
</html>
<html>
<script>
</script>
<body>
<video width="320" height="240" controls>
<source src="http://localhost:1337/music2" type="video/mp4">
Your browser does not support the video tag.
</video>
</body>
</html>
我希望能够不止一次调用localhost:1337 / music,但是当我在Google Chrome(或Firefox或Internet Explorer 11)的两个标签中调用localhost:1337 / home时页面不会加载音频,直到所有字节都已传输给localhost:1337 / music的第一个请求。代码是异步的,我知道它不会阻塞,因为如果阻塞,第二个请求... / home2不应该提供文件。
有人知道异步代码阻塞的原因吗?我通过Chrome中的开发人员工具验证了正在调用/ music和/ music2(从浏览器的角度来看)。我也遇到了不使用Express的同样问题,所以我确信它不是框架。
答案 0 :(得分:2)
Chrome一次只下载一个文件的副本(例如,如果您下载了一个非常大的文件,对该文件的后续请求就会排队,甚至跨标签)。开发环境表示请求正在等待处理,但是挂起的实际上是Chrome的限制,而不是Node JS服务器的限制。文件下载专门与URL作为密钥绑定,这就是为什么我能够让不同的URL下载相同的文件,以及为什么我可以在下载此文件时向服务器发出其他请求。
答案 1 :(得分:-1)
您可能遇到了浏览器的连接限制。尝试增加限制(如果可以的话,我认为你至少可以在Firefox中这样做)并再试一次。
此外,您只需将文件传输到响应,而不是手动收听数据&#39;并且&#39;结束&#39;。例如:
app.get('/music2', function(req, res){
console.log("/music2")
//res.sendFile('C:\\Users\\Owner\\AppData\\Roaming\\npm\\01 Give Life Back To Music.mp4');
var readStream = fs.createReadStream('C:\\Users\\Owner\\AppData\\Roaming\\npm\\01 Give Life Back To Music.mp4');
console.log("/afterRead");
readStream.pipe(res);
});
答案 2 :(得分:-1)
似乎createReadStream是阻止文件。我试过这段代码
var http = require('http');
var fs = require('fs');
var qs = require('querystring');
http.createServer(function (req, res) {
var str = req.url.split('?')[1];
var query = qs.parse(str);
var readStream = fs.createReadStream('./response' + (query.q || '') + '.json');
readStream.on('data', function(data) {
var flushed = res.write(data);
console.log( 'streaming data' );
if(!flushed){
readStream.pause();
}
});
res.on('drain', function() {
readStream.resume();
});
}).listen(1337, '127.0.0.1');
并打开了两个带有localhost
和localhost/?q=1
的标签,它可以很好地读取两个单独的文件,但如果您尝试通过两个进程读取一个文件,则第二个请求会挂起。