在創建流(A)、創建另一個流(B)和讀取流(B)之后,讀取程序從流(A)停止。我怎么解決這個問題?
Node.js v14.18.1
import * as readline from 'readline';
import { Readable } from 'stream';
async function main() {
const streamA = Readable.from('a');
const readerA = readline.createInterface({
input: streamA,
crlfDelay: Infinity
});
var stopCase = false;
if (stopCase) {
const streamB = Readable.from('b');
const readerB = readline.createInterface({
input: streamB,
crlfDelay: Infinity
});
console.log('readB');
for await (const line of readerB) {
console.log(line);
}
}
console.log(`readerA.closed = ${'closed' in readerA}`);
console.log('readA');
for await (const line of readerA) {
console.log(line);
}
console.log('success');
}
main();
輸出(stopCase=true):
readB
b
readerA.closed = true
readA
輸出(stopCase=false):
readerA.closed = false
readA
a
success
uj5u.com熱心網友回復:
問題是,一旦你這樣做:
const readerA = readline.createInterface({
input: streamA,
crlfDelay: Infinity
});
然后,streamA現在準備好流動并readerA準備好在您點擊事件回圈后立即生成事件。當你進入stopCase塊并點擊 時for await (const line of readerB),這將允許streamA流動,這將允許readerA觸發事件。
但是,當 readerA 事件觸發時,您不會監聽它們,因此它streamA會在您不收聽時完成它所擁有的內容。
如果readerA在完成stopCase塊之后才創建,您可以看到它如何更好地作業。因為當你擊中塊的內部時,streamA和readerA還沒有流動。awaitstopCase
這就是我所說的由于嘗試向事件驅動的流中添加承諾而引起的日益增長的痛苦。如果您將流保持在流動狀態,并且您打算使用await這些事件來讀取這些事件,但是您隨后進行await了其他一些承諾,那么當您尚未偵聽時,第一個流上的所有事件都會觸發。它不知道您正在等待使用await它。您將其設定為流動,以便解釋器一進入事件回圈,它就會開始流動,即使您沒有使用await.
我之前在我自己的代碼中遇到過這個問題,解決方案是在您即將使用await它來讀取它之前,或者直到您有一個更傳統的事件處理程式配置為偵聽任何事件之前,不要將流設定為流動那流量。基本上,您不能同時配置兩個流for await (...)。配置一個流,將它與您的 一起使用for await (...),然后配置另一個。并且,還要注意在for await (...)回圈處理中使用的任何其他承諾。使用這種結構時,有很多方法可以搞砸。
在我看來,如果流實際上處于不同的狀態以與承諾一起使用,它會更可靠地作業,因此它只會通過承諾介面流動。那么,這種事情就不會發生了。但是,我相信該實施也存在許多挑戰。
例如,如果您這樣做:
import * as readline from 'readline';
import { Readable } from 'stream';
async function main() {
var stopCase = true;
console.log(`stopCase = ${stopCase}`);
if (stopCase) {
const streamB = Readable.from('b');
const readerB = readline.createInterface({
input: streamB,
crlfDelay: Infinity
});
console.log('readB');
for await (const line of readerB) {
console.log(line);
}
}
const streamA = Readable.from('a');
const readerA = readline.createInterface({
input: streamA,
crlfDelay: Infinity
});
console.log(`streamA flowing = ${streamA.readableFlowing}`);
console.log(`readerA.closed = ${!!readerA.closed}`);
console.log('readA');
for await (const line of readerA) {
console.log(line);
}
console.log('success');
}
main();
然后,您將獲得所有輸出:
stopCase = true
readB
b
streamA flowing = true
readerA.closed = false
readA
a
success
您從未獲得的原因console.log('success')可能是因為您遇到了for await (const line of readerA) { ...}回圈,并且它在沒有更多資料的承諾下停止了。同時,nodejs 注意到行程中沒有任何東西可以創建任何未來的事件,因此它退出了行程。
您可以在更簡單的應用程式中看到相同的概念:
async function main() {
await new Promise(resolve => {
// do nothing
});
console.log('success');
}
main();
它等待一個永遠不會完成的承諾,并且在應用程式中沒有任何創建事件的事件,因此 nodejs 只是關閉并記錄日志success。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/373419.html
