如果我正确理解Node,则侦听器将仅接收附加后发生的事件。假设missing.txt是一个丢失的文件。这有效:
'use strict';
const fs = require( 'fs' );
var rs = fs.createReadStream( 'missing.txt' );
rs.on('error', (err) => console.log('error ' + err) );
它产生:错误错误:ENOENT:没有这样的文件或目录,打开... \ missing.txt
为什么这样做?如下更改第四行也有效:
setTimeout( () => rs.on('error', (err) => console.log('error ' + err)) , 1);
但是将超时更改为5毫秒,并将错误作为未处理的事件抛出。
如果添加事件监听器的延迟很短,我是否设置了碰巧发出错误的竞赛?这是否意味着我真的应该在将文件作为流打开之前对文件的存在进行明确检查?但这可能会创建另一场比赛,因为Node docs state与fs.exists有关:“其他进程可能会改变文件在两次调用之间的状态。” Moroeover,事件监听器很方便,因为它会捕获其他错误。
最佳做法是假设在不引入显式延迟的情况下,事件监听器的添加速度足以听到尝试流式传输不存在的文件时出错吗?
答案 0 :(得分:1)
如果不存在此类位置或创建权限不在用户程序中,则会发生此错误。
这可能会有所帮助:
var filename = __dirname+req.url;
var readStream = fs.createReadStream(filename);
readStream.on('open', function () {
readStream.pipe(res);
});
readStream.on('error', function(err) {
res.end(err);
});
为什么你在超时时听错了?
由于
答案 1 :(得分:0)
从<{1}}获取ReadStream
实例后发生的任何错误都不会被抛出/发出,直到至少下一个滴答。因此,只要您同步执行此操作,就可以在创建后始终将“错误”侦听器附加到流中。您的fs.createReadStream()
实验有时会起作用,因为ReadStream
会在其构造函数的末尾调用setTimeout
。 ReadStream.prototype.open()
方法调用this.open()
从您提供的文件路径中获取文件描述符。由于这也是一个异步函数,这意味着当您在fs.open()
中附加“错误”侦听器时,您正在创建竞争条件。
因此,它首先发生,setTimeout
调用带有错误的回调,或者fs.open()
调用其回调来附加'错误'监听器。在创建setTimeout()
实例后附加“错误”监听器是完全没问题的,只要确保同步执行它就不会遇到竞争条件问题。