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

时间:2015-12-31 02:10:56

标签: node.js stream

我正在尝试将一些音频流式传输到我的服务器,然后将其流式传输到用户指定的服务,用户将向我提供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);
    });

输出:

如果主机名正确:

    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

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

  

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

     

添加'data'事件处理程序以侦听数据。

     

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

     

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

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

1 个答案:

答案 0 :(得分:1)

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

  

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

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

  

但是如何检测我何时应该做以上任何一项?

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

首先尝试设置一个低超时请求(小于someHostReq.on('error')需要触发,因为对你而言似乎太多了)request.setTimeout(timeout[, callback])并检查当正确的主机名是否没有失败。如果有效,只需使用callbacktimeout事件来检测服务器timeOut的时间并使用上述技术之一到达目的地。

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

  

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

触发时触发错误。你无法“立即”检测到它。 ¿为什么不在发送流之前发送证明信标请求来检查支持?某种:

“用户指定的Cheking服务......”If确定 - >管道用户请求流服务OR FAIL - >通知用户有关错误的服务。