我正在尝试将一些音频流式传输到我的服务器,然后将其流式传输给用户指定的服务,用户将向我提供someHostName
,它有时不支持这种类型的请求。
我的问题是,当发生这种情况时,clientRequest.on('end',..)
从未被激发,我认为这是因为它被管道传输到someHostReq
,而当someHostName
"错误"时,它就会变得一团糟。
我的问题是:
即使流clientRequest
管道有问题,我是否仍然可以激发clientRequest.on('end',..)
?
如果不是:我如何"立即"检测出someHostReq
出现了问题?someHostReq.on('error')
只有一段时间后才会启动。
代码:
someHostName = 'somexample.com'
function checkIfPaused(request){//every 1 second check .isPaused
console.log(request.isPaused()+'>>>>');
setTimeout(function(){checkIfPaused(request)},1000);
}
router.post('/', function (clientRequest, clientResponse) {
clientRequest.on('data', function (chunk) {
console.log('pushing data');
});
clientRequest.on('end', function () {//when done streaming audio
console.log('im at the end');
}); //end clientRequest.on('end',)
options = {
hostname: someHostName, method: 'POST', headers: {'Transfer-Encoding': 'chunked'}
};
var someHostReq = http.request(options, function(res){
var data = ''
someHostReq.on('data',function(chunk){data+=chunk;});
someHostReq.on('end',function(){
console.log('someHostReq.end is called');
});
});
clientRequest.pipe(someHostReq);
checkIfPaused(clientRequest);
});
输出:
如果主机名正确:
pushing data
.
.
pushing data
false>>>
pushing data
.
.
pushing data
pushing data
false>>>
pushing data
.
.
pushing data
console.log('im at the end');
true>>>
//continues to be true, that's fine
在主机名错误的情况下:
pushing data
.
.
pushing data
false>>>>
pushing data
.
.
pushing data
pushing data
false>>>>
pushing data
.
.
pushing data
true>>>>
true>>>>
true>>>>
//it stays true and clientRequest.on('end') is never called
//even tho the client is still streaming data, no more "pushing data" appears
如果你认为我的问题是重复的:
与此不同:node.js http.request事件流-我的END事件去了哪里,OP只是进行GET而不是POST
与此不同:node.js中的http.createserver;不起作用,流处于暂停模式,因为没有发生以下任何情况:
您可以通过执行以下任一操作切换到流动模式:
添加"data"事件处理程序以侦听数据。
调用resume()方法以显式打开流。
调用pipe()方法将数据发送到可写表。
来源:https://nodejs.org/api/stream.html#stream_class_stream_readable
- 这与以下不同:来自http请求的Node.js响应没有调用';end';不包括';数据';事件,他只是忘记添加
.on('data',..)
在主机名错误的情况下,缓冲区的行为似乎有问题,如果目标流缓冲区已满(因为someHost没有获得发送的数据块),管道将不会继续读取源流,因为管道会自动管理流。由于管道未读取原始流,您永远无法到达"结束"事件。
是否仍然可以在('end',..)上激发clientRequest.on即使流clientRequest管道到有问题它
除非数据被完全消耗掉,否则"end"事件不会激发。要用暂停的流激发"end",您需要调用resume()
(首先从错误的主机名中取消绑定,否则您将再次陷入缓冲区阻塞),以将蒸汽再次设置为flowMode或read()
。
但是,如何检测我什么时候应该做上述任何一项?
someHostReq.on('error')是一个自然的地方,但如果它需要很长时间才能启动:
首先尝试设置一个较低的超时请求(小于someHostReq.on('error')触发所需的时间,这对您来说似乎太长了)request.setTimeout(timeout[, callback])
,并检查在正确的主机名时它是否没有失败。如果有效,只需使用callback
或timeout
事件来检测服务器超时的时间,并使用上面的一种技术到达最后。
如果超时解决方案失败或不符合您的要求,您必须使用clientRequest.on('data')
、clientRequest.on('end')
和/或clienteRequest.isPaused
中的标志来猜测何时被缓冲区卡住。当你认为你被卡住了,只需应用上面的一种技术就可以到达流的末尾。幸运的是,与等待someHostReq.on('error')
相比,检测缓冲区卡住所需的时间更少(可能可以找到两个未到达data'
的request.isPaused() = true
事件来确定您是否被卡住)。
如何检测someHostReq出现错误"立即"?someHostReq.on('error')除了在一段时间。
触发时会触发错误。你不能"立即"检测到它。?为什么不在管道流之前发送一个证明信标请求来检查支持?某种:
"检查用户指定的服务…"If
OK->将用户请求流管道传输到服务OR
FAIL->通知用户错误的服务。