read.on('end',...)永远不会被解雇

bub*_*uba 5 stream node.js

我正在尝试将一些音频流式传输到我的服务器,然后将其流式传输到用户指定的服务,用户将提供给我someHostName,有时可能不支持该类型的请求.

我的问题是,当它发生时,它clientRequest.on('end',..)永远不会被解雇,我认为这是因为someHostReq当它someHostName被"错误" 时,它被管道传输被搞砸了.

我的问题是:

无论如何,clientRequest.on('end',..)即使流clientRequest管道出现问题,我仍然可以解雇它吗?

如果不是:如何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);
    });
Run Code Online (Sandbox Code Playgroud)

输出:

在正确的主机名的情况下:

    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
Run Code Online (Sandbox Code Playgroud)

如果主机名错误:

    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
Run Code Online (Sandbox Code Playgroud)

如果你认为我的问题是重复的:

您可以通过执行以下任一操作切换到流动模式:

添加"数据"事件处理程序以侦听数据.

调用resume()方法显式打开流.

调用pipe()方法将数据发送到Writable.

来源:https://nodejs.org/api/stream.html#stream_class_stream_readable

jlv*_*ero 4

主机名错误的情况下的行为似乎存在缓冲区问题,如果目标流缓冲区已满(因为 someHost 没有获取发送的数据块),管道将不会继续读取原始流,因为管道自动管理流。由于管道没有读取原始流,因此您永远不会到达“结束”事件。

\n\n
\n

无论如何,即使流 clientRequest 管道出现问题,我仍然可以触发 clientRequest.on(\'end\',..) 吗?

\n
\n\n

除非数据完全消耗,否则“结束”事件不会触发。要使用暂停的流触发“end”,您需要调用resume()(首先从错误的主机名取消管道,否则您将再次陷入缓冲区卡住)以再次将蒸汽设置为 flowMode 或read()结束。

\n\n
\n

但是如何检测何时应该执行上述任何操作呢?

\n
\n\n

someHostReq.on(\'error\') 是自然的地方,但如果启动时间太长:

\n\n

首先尝试设置一个较低的超时请求(小于 someHostReq.on(\'error\') 触发所需的时间,因为对您来说似乎花费了太多时间) request.setTimeout(timeout[, callback])并检查在正确的主机名时它是否不会失败。如果有效,只需使用callbacktimeout事件来检测服务器何时超时,并使用上述技术之一到达终点。

\n\n

如果超时解决方案失败或不符合您的要求,您必须使用 中的标志clientRequest.on(\'data\')clientRequest.on(\'end\')和/或 clienteRequest.isPaused猜测您何时被缓冲区卡住。当您认为自己陷入困境时,只需应用上述技术之一即可到达流的末尾。幸运的是,检测缓冲区卡住所需的时间比等待的时间要少someHostReq.on(\'error\')(可能两个request.isPaused() = true未到达\'data\'事件足以确定您是否被卡住)。

\n\n
\n

如何“立即”检测到 someHostReq\n 发生了错误?someHostReq.on(\'error\') 除非经过一段时间后才会启动。

\n
\n\n

错误触发时触发。您无法“立即”检测到它。\xc2\xbf为什么不在管道流之前发送一个证明信标请求来检查支持?一些:

\n\n

“检查用户指定的服务...” IfOK -> 将用户请求流传送到服务ORFAIL -> 通知用户错误的服务。

\n