【问题标题】:How to write string data to a stream in chunks, not a lump如何将字符串数据以块的形式写入流,而不是块
【发布时间】:2020-01-24 02:38:45
【问题描述】:

我有一个 node.js 脚本,它必须在 STDIN 上接受 utf8 数据并在 STDOUT 上输出其他 utf8 数据 它旨在通过外壳管道接受来自磁带测试框架运行器的 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 输出(没有“块”标记)拆分为字符串数组(相当于 实时输出中的块),并尝试在单独的写入调用中写入每个字符串到 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 仅读取了一次数据,上面有一个块标记。我试图在写调用之前在 forEach 循环中发出“可读”事件,但这也无济于事:

chunksOriginal.forEach((chunk, i) => {
  spawned.stdin.emit('readable');
  spawned.stdin.write(chunk);
});

我怀疑问题是我在概念上不了解 node.js 和 bash 中的 IPC。 “实时输出”中的数据可能是通过所谓的 node.js 缓冲区写入的。

我并不是要求问题的确切解决方案,但如果有人提供,我将不胜感激。

只是一个概念层面的提示,我应该在哪里查看,在什么文档中,以解决这个问题

【问题讨论】:

    标签: javascript node.js io ipc


    【解决方案1】:

    我也尝试使用setTimeout,使写入过程异步,虽然我忘了在问题中提到这一点,但它也没有帮助:

    chunksOriginal.forEach((chunk, i) => {
      setTimeout(() => {
        spawned.stdin.emit('readable');
        spawned.stdin.write(chunk);
      }, i);
    });
    

    然后我又试了一次,也就是增加了延迟i * 100ms,果然奏效了:

    chunksOriginal.forEach((chunk, i) => {
      setTimeout(() => {
        spawned.stdin.write(chunk);
      }, i * 100);
    });
    

    这很有帮助,现在format.js 从虚拟输入接收到的块数量与从实时输入接收到的块数量相同(尽管这一切都可能需要一些调整、配置创建)。

    另外值得注意的是,发出调用是不必要的

    【讨论】:

      猜你喜欢
      • 2019-03-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-28
      • 1970-01-01
      • 2012-08-18
      • 2023-04-06
      • 1970-01-01
      相关资源
      最近更新 更多