这是我在节点 v14.4.0 中提炼成最小的、可重现的示例的更大过程的一部分。在这段代码中,它不会从for
循环内部输出任何内容。
我在控制台中只看到这个输出:
before for() loop
finished
finally
done
for await (const line1 of rl1)
循环永远不会进入循环for
- 它只是跳过它:
const fs = require('fs');
const readline = require('readline');
const { once } = require('events');
async function test(file1, file2) {
try {
const stream1 = fs.createReadStream(file1);
await once(stream1, 'open');
const rl1 = readline.createInterface({input: stream1, crlfDelay: Infinity});
const stream2 = fs.createReadStream(file2);
await once(stream2, 'open');
const rl2 = readline.createInterface({input: stream2, crlfDelay: Infinity});
console.log('before for() loop');
for await (const line1 of rl1) {
console.log(line1);
}
console.log('finished');
} finally {
console.log('finally');
}
}
test("data/numbers.txt", "data/letters.txt").then(() => {
console.log(`done`);
}).catch(err => {
console.log('Got rejected promise:', err);
})
但是,如果我删除其中任何一个await once(stream, 'open')
语句,那么for
循环就会完全按照预期执行(列出rl1
文件的所有行)。因此,显然,来自 readline 接口和流之间的异步迭代器存在一些计时问题。任何想法可能发生的事情。知道什么可能导致这个问题或如何解决它吗?
仅供参考,这await once(stream, 'open')
是因为异步迭代器中的另一个错误,如果打开文件时出现问题,它不会拒绝,而如果无法打开文件,则会await once(stream, 'open')
导致您正确地获得拒绝(基本上是在飞行前打开) .
如果您想知道为什么存在 stream2 代码,它在较大的项目中使用,但我已将此示例缩减为最小的、可重现的示例,并且只需要这么多代码来演示问题。
编辑:在尝试稍微不同的实现时,我发现如果我将两个once(stream, "open")
调用组合在 aPromise.all()
中,它就会起作用。所以,这有效:
const fs = require('fs');
const readline = require('readline');
const { once } = require('events');
async function test(file1, file2) {
try {
const stream1 = fs.createReadStream(file1);
const rl1 = readline.createInterface({input: stream1, crlfDelay: Infinity});
const stream2 = fs.createReadStream(file2);
const rl2 = readline.createInterface({input: stream2, crlfDelay: Infinity});
// pre-flight file open to catch any open errors here
// because of existing bug in async iterator with file open errors
await Promise.all([once(stream1, "open"), once(stream2, "open")]);
console.log('before for() loop');
for await (const line1 of rl1) {
console.log(line1);
}
console.log('finished');
} finally {
console.log('finally');
}
}
test("data/numbers.txt", "data/letters.txt").then(() => {
console.log(`done`);
}).catch(err => {
console.log('Got rejected promise:', err);
});
这显然不应该对您等待文件打开的确切方式敏感。某处存在一些计时错误。我想在 readline 或 readStream 上找到该错误并将其归档。有任何想法吗?