在实现简单的静态服务中间件时,我偶然发现了以下代码:
fs = require('fs');
util = require('util');
stream = fs.createReadStream('/');
stream.on('open', function(fd) { console.log('opened! ' + util.inspect(fd)); });
stream.on('error', function(err) { console.log('error! ' + util.inspect(err)); });
当参数是目录时,open
和 error
事件都会被触发!
$ node test.js opened! 11 error! { [Error: EISDIR, read] errno: 28, code: 'EISDIR' }
我假设我有 open
或 error
,从来没有同时发生过。
什么是区分好 open
和坏 open
而不求助于显式测试 fd
和 stat
是目录?还有其他类似的案例吗?
最佳答案
当您在 Node 中创建可读流时,代码将尝试打开文件并读取内容(如果未提供 fd
)。你可以通过代码看到:
调用createReadStream()
会创建一个ReadStream
对象,如果fd
,它将调用this.open()
不是数字(link to source):
if (!util.isNumber(this.fd))
this.open();
这会调用 fs.open
,我猜这会在目录上打开目录? (这有点奇怪为什么允许它没有错误地工作,但代码最终会命中 native 绑定(bind)层并继续。)打开它后,代码发出“打开”事件并开始读取内容文件(link to source):
ReadStream.prototype.open = function() {
var self = this;
fs.open(this.path, this.flags, this.mode, function(er, fd) {
if (er) {
if (self.autoClose) {
self.destroy();
}
self.emit('error', er);
return;
}
self.fd = fd;
self.emit('open', fd);
// start the flow of data.
self.read();
});
};
在调用 fs.read
期间导致错误,该错误被发送到 ReadStream
的回调 onRead
( link to source ) :
function onread(er, bytesRead) {
if (er) {
if (self.autoClose) {
self.destroy();
}
self.emit('error', er);
因为 createReadStream
调用立即打开并开始读取文件内容(如果未传递文件描述符),事件将如您所见发出。首先是 open
事件,然后尝试读取文件,但失败了,并且发出了 error
事件。
因为这是一个 readable stream ,你可能需要考虑监听 data
事件而不是 open
事件来判断这是否是一个可接受的文件,因为你是立即阅读。类似这样的东西:
fs = require('fs');
util = require('util');
stream = fs.createReadStream('/');
stream.on('data', function(chunk) { console.log('data! ' + chunk.toString()); });
stream.on('error', function(err) { console.log('error! ' + util.inspect(err)); });
在测试中,您将在文件上点击 data
,在目录上点击 error
。
关于javascript - `open` 和 `error` 同时与 fs.createReadStream() 和 EISDIR,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24377582/