Node.js - 在管道响应之前检查流是否有错误 [英] Node.js - Check if stream has error before piping response

查看:26
本文介绍了Node.js - 在管道响应之前检查流是否有错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 Node.js 中,假设我想从某处读取文件并流式传输响应(例如,使用 fs.createReadStream() 从文件系统中读取).

In Node.js, say that I want to read a file from somewhere and stream the response (e.g., from the filesystem using fs.createReadStream()).

application.get('/files/:id', function (request, response) {
    var readStream = fs.createReadStream('/saved-files/' + request.params.id);
    var mimeType = getMimeTypeSomehow(request.params.id);
    if (mimeType === 'application/pdf') {
        response.set('Content-Range', ...);
        response.status(206);
    } else {
        response.status(200);
    }
    readStream.pipe(response);
});

但是,我想在发送响应头之前检测流是否有错误.我该怎么做?

However, I want to detect if there is an error with the stream before sending my response headers. How do I do that?

伪代码:

application.get('/files/:id', function (request, response) {
    var readStream = fs.createReadStream('/saved-files/' + request.params.id);
    readStream.on('ready', function () {
        var mimeType = getMimeTypeSomehow(request.params.id);
        if (mimeType === 'application/pdf') {
            response.set('Content-Range', ...);
            response.status(206);
        } else {
            response.status(200);
        }
        readStream.pipe(response);
    });
    readStream.on('error', function () {
        response.status(404).end();
    });
});

推荐答案

当 readStream 结束或有错误时,写入流结束.您可以通过在管道期间传递 end:false 并手动结束写入流来防止这种默认行为.

Write stream is ended when readStream ends or has an error. You can prevent this default behaviour by passing end:false during pipe and end the write stream manually.

因此,即使发生错误,您的写入流仍处于打开状态,您可以在 error 回调中使用 writestream 执行其他操作(例如发送 404 状态).

So even if the error occurs, your write stream is still open and you can do other stuff(e.g. sending 404 status) with writestream in the error callback.

var readStream = fs.createReadStream('/saved-files/' + request.params.id);
readStream.on('error', function () {
    res.status(404).end();
});
readStream.on('end', function(){
  res.end(); //end write stream manually when readstream ends
})
readStream.pipe(res,{end:false}); // prevent default behaviour

<小时>

更新 1:对于文件流,您可以监听 open 事件以检查文件是否已准备好读取:


Update 1: For file streams, you can listen for open event to check if the file is ready to read:

readStream.on('open', function () {
    // set response headers and status
});

<小时>

更新 2:正如 OP 提到的,其他流可能没有 open 事件,如果流是从节点的流模块继承的,我们可以使用以下内容.诀窍是我们手动编写数据而不是 pipe() 方法.这样我们就可以在开始写入第一个字节之前对可写进行一些初始化".


Update 2: As OP mentioned there may be no open event for other streams, we may use the following if the stream is inherited from node's stream module. The trick is we write the data manually instead of pipe() method. That way we can do some 'initialization' on writable before starting to write first byte.

所以我们先绑定once('data'),然后绑定on('data').第一个将在实际写入发生之前被调用.

So we bind once('data') first and then bind on('data'). First one will be called before actual writing is happened.

readStream
.on('error',function(err) {
  res.status(404).end();
})
.once('data',function(){ 
  //will be called once and before the on('data') callback
  //so it's safe to set headers here
  res.set('Content-Type', 'text/html');
})
.on('data', function(chunk){ 
  //now start writing data 
  res.write(chunk);
})
.on('end',res.end.bind(res)); //ending writable when readable ends

这篇关于Node.js - 在管道响应之前检查流是否有错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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