这是一个更大流程的一部分,我在节点 v14.4.0 中将其提炼为最小的、可重现的示例。在此代码中,它从内部不输出任何内容for
loop.
我在控制台中只看到这个输出:
before for() loop
finished
finally
done
The 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 代码,它是在较大的项目中使用的,但我已将此示例简化为最小的、可重现的示例,并且只需要这么多代码来演示该问题。
Edit:在尝试稍微不同的实现时,我发现如果我将两者结合起来once(stream, "open")
调用一个Promise.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 上找到该错误并将其归档。有任何想法吗?