如何以块而不是块的形式将字符串数据写入流
How to write string data to a stream in chunks, not a lump
我有一个 node.js 脚本,它必须在 STDIN 上接受 utf8 数据并在 STDOUT 上输出其他 utf8 数据
它旨在通过 shell 管道接受来自磁带测试框架 运行ner 的 TAP 字符串,并稍微修改它:
#!/usr/bin/env node
'use strict';
process.stdin.setDefaultEncoding('utf8');
process.stdout.setDefaultEncoding('utf8');
process.stdin.on('readable', () => {
let chunk;
while ((chunk = process.stdin.read()) !== null) {
process.stdout.write('chunk: ' + chunk);
}
});
process.stdin.on('end', () => {
process.stdout.write('end\n');
});
当我 运行 对其进行磁带测试时 npm run test-unit test/unit/main.test.js | ./format.js
我得到(我将进一步将其称为“实时输出”):
chunk:
> dummy@0.0.0 test-unit /path/dummy/zzz
> tape "test/unit/main.test.js"
chunk: TAP version 13
chunk: # test 1
chunk: # comment 1
chunk: ok 1 should be equal
chunk:
1..1
chunk: # tests 1
# pass 1
# ok
chunk:
end
所以你可以看到,数据被写入了 8 次,分为 8 个块。
我的问题是,如何在测试中模拟这种行为?
在测试中,我使用 spawn('./format.js')
生成了另一个进程,但我如何写入该进程的 STDIN,以便读取相同的数据需要 8 次,就像来自 tap 报告器一样。
我将原始的 tap 输出(没有 "chunk" 标记)拆分为一个字符串数组(相当于 实时输出 中的块)并尝试编写每个字符串在对 spawned.stdin 的单独写入调用中然后测试 format.js
的输出:
let spawned = spawn('./format.js');
let chunksOriginal = [
// chunks here
];
spawned.stdout.on('readable', () => {
console.log(spawned.stdout.read());
});
chunksOriginal.forEach((chunk, i) => {
spawned.stdin.write(chunk);
});
我希望 console.log
输出与 实时输出相同的字符串 ,或者至少是它的第一个块,但我得到了:
chunk:
> dummy@0.0.0 test-unit /path/dummy/zzz
> tape "test/unit/main.test.js"
TAP version 13
# test 1
# comment 1
ok 1 should be equal
1..1
# tests 1
# pass 1
# ok
end
如您所见,format.js
只读取了一次数据,上面有一个块标记。我试图在 write 调用之前在 forEach 循环中发出 "readable" 事件,这也没有帮助:
chunksOriginal.forEach((chunk, i) => {
spawned.stdin.emit('readable');
spawned.stdin.write(chunk);
});
我怀疑问题是我不理解 node.js 和 bash 中的 IPC 概念。 "live output" 中的数据可能是通过所谓的 node.js 缓冲区写入的。
我不是在寻求问题的确切解决方案,但如果有人提供,我将不胜感激。
只是概念层面的提示,我应该在哪里看什么文档来解决这个问题
我还尝试使用 setTimeout
来使写入过程异步,虽然我忘记在问题中提及这一点,但它也没有帮助:
chunksOriginal.forEach((chunk, i) => {
setTimeout(() => {
spawned.stdin.emit('readable');
spawned.stdin.write(chunk);
}, i);
});
然后我又试了一次,增加了延迟 i * 100
毫秒,成功了:
chunksOriginal.forEach((chunk, i) => {
setTimeout(() => {
spawned.stdin.write(chunk);
}, i * 100);
});
这很有帮助,现在 format.js
从虚拟输入接收到与从实时输入接收到的块数量相同的块(尽管可能都需要一些调整,配置创建)。
另外值得注意的是,emit 调用是不必要的。
我有一个 node.js 脚本,它必须在 STDIN 上接受 utf8 数据并在 STDOUT 上输出其他 utf8 数据 它旨在通过 shell 管道接受来自磁带测试框架 运行ner 的 TAP 字符串,并稍微修改它:
#!/usr/bin/env node
'use strict';
process.stdin.setDefaultEncoding('utf8');
process.stdout.setDefaultEncoding('utf8');
process.stdin.on('readable', () => {
let chunk;
while ((chunk = process.stdin.read()) !== null) {
process.stdout.write('chunk: ' + chunk);
}
});
process.stdin.on('end', () => {
process.stdout.write('end\n');
});
当我 运行 对其进行磁带测试时 npm run test-unit test/unit/main.test.js | ./format.js
我得到(我将进一步将其称为“实时输出”):
chunk:
> dummy@0.0.0 test-unit /path/dummy/zzz
> tape "test/unit/main.test.js"
chunk: TAP version 13
chunk: # test 1
chunk: # comment 1
chunk: ok 1 should be equal
chunk:
1..1
chunk: # tests 1
# pass 1
# ok
chunk:
end
所以你可以看到,数据被写入了 8 次,分为 8 个块。
我的问题是,如何在测试中模拟这种行为?
在测试中,我使用 spawn('./format.js')
生成了另一个进程,但我如何写入该进程的 STDIN,以便读取相同的数据需要 8 次,就像来自 tap 报告器一样。
我将原始的 tap 输出(没有 "chunk" 标记)拆分为一个字符串数组(相当于 实时输出 中的块)并尝试编写每个字符串在对 spawned.stdin 的单独写入调用中然后测试 format.js
的输出:
let spawned = spawn('./format.js');
let chunksOriginal = [
// chunks here
];
spawned.stdout.on('readable', () => {
console.log(spawned.stdout.read());
});
chunksOriginal.forEach((chunk, i) => {
spawned.stdin.write(chunk);
});
我希望 console.log
输出与 实时输出相同的字符串 ,或者至少是它的第一个块,但我得到了:
chunk:
> dummy@0.0.0 test-unit /path/dummy/zzz
> tape "test/unit/main.test.js"
TAP version 13
# test 1
# comment 1
ok 1 should be equal
1..1
# tests 1
# pass 1
# ok
end
如您所见,format.js
只读取了一次数据,上面有一个块标记。我试图在 write 调用之前在 forEach 循环中发出 "readable" 事件,这也没有帮助:
chunksOriginal.forEach((chunk, i) => {
spawned.stdin.emit('readable');
spawned.stdin.write(chunk);
});
我怀疑问题是我不理解 node.js 和 bash 中的 IPC 概念。 "live output" 中的数据可能是通过所谓的 node.js 缓冲区写入的。
我不是在寻求问题的确切解决方案,但如果有人提供,我将不胜感激。
只是概念层面的提示,我应该在哪里看什么文档来解决这个问题
我还尝试使用 setTimeout
来使写入过程异步,虽然我忘记在问题中提及这一点,但它也没有帮助:
chunksOriginal.forEach((chunk, i) => {
setTimeout(() => {
spawned.stdin.emit('readable');
spawned.stdin.write(chunk);
}, i);
});
然后我又试了一次,增加了延迟 i * 100
毫秒,成功了:
chunksOriginal.forEach((chunk, i) => {
setTimeout(() => {
spawned.stdin.write(chunk);
}, i * 100);
});
这很有帮助,现在 format.js
从虚拟输入接收到与从实时输入接收到的块数量相同的块(尽管可能都需要一些调整,配置创建)。
另外值得注意的是,emit 调用是不必要的。