You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Node.js中向Deno子进程传输大JSON数据集?

Node.js向Deno子进程通过STDIN传输大JSON数据的正确实现方式

一、发送端(Node.js)的修正方案

你的核心问题之一是手动处理drain事件的逻辑有误,且未正确关闭STDIN告知Deno数据传输完成。推荐使用Node.js内置的stream/promises模块的pipeline方法,它会自动处理背压,无需手动监听drain:

const { spawn } = require('child_process');
const { pipeline } = require('stream/promises');
const { Readable } = require('stream');

const deno = spawn('deno', ['run', '--allow-all', '--unstable-bare-node-builtins', '--unstable-sloppy-imports', `--allow-read=${cwd}`, filename], {
    stdio: ['pipe', 'pipe', 'pipe'],
    cwd,
    env: {
        PATH: process.env.PATH,
        DENO_NO_PACKAGE_JSON: '1'
    }
});

// 将大JSON转为可读流,避免一次性占用过多内存
const payloadStream = Readable.from(JSON.stringify(yourLargeDataset));
// 通过pipeline自动处理背压并完成写入
await pipeline(payloadStream, deno.stdin);
// 关闭STDIN,告知Deno数据传输结束
deno.stdin.end();

如果坚持手动处理drain,需修正逻辑(Node.js的Writable.write返回布尔值而非Promise):

const writeChunk = (chunk: Buffer): Promise<void> => {
    return new Promise((resolve) => {
        const canContinue = deno.stdin.write(chunk);
        if (canContinue) {
            resolve();
        } else {
            deno.stdin.once('drain', resolve);
        }
    });
};

// 使用示例:
const payloadBuffer = Buffer.from(JSON.stringify(yourLargeDataset));
await writeChunk(payloadBuffer);
deno.stdin.end();

二、接收端(Deno)的正确处理

Deno端必须读取STDIN的全部数据后再解析JSON,否则会因接收不完整导致解析失败:

// Deno端代码
const decoder = new TextDecoder();
// 读取STDIN所有数据直到EOF
const rawData = await Deno.readAll(Deno.stdin);
const jsonData = JSON.parse(decoder.decode(rawData));
// 处理数据
console.log(jsonData);

如果需要流式处理(超大规模JSON),需拼接所有chunk后再解析:

const decoder = new TextDecoder();
let buffer = '';
// 逐块读取STDIN流
for await (const chunk of Deno.stdin.readable) {
    buffer += decoder.decode(chunk);
}
const jsonData = JSON.parse(buffer);

三、解决ENOTTY: Not a Typewriter错误

该错误是因为Deno代码尝试将STDIN当作TTY终端处理(例如使用prompt()、readline模块等)。解决方式:

  1. 移除Deno代码中所有依赖TTY的交互逻辑,改为直接读取STDIN流。
  2. 确保Node.js启动Deno时的stdio配置为['pipe', 'pipe', 'pipe'](你的代码已正确设置)。

四、额外优化建议

  • 预发送数据长度:如果JSON体积极大,可先发送数据字节长度,Deno端先读取长度再精准读取对应字节数,避免流分割问题:
    // Node.js端
    const payload = JSON.stringify(yourLargeDataset);
    const lengthBuffer = Buffer.from(`${Buffer.byteLength(payload, 'utf8')}\n`);
    await pipeline(Readable.from([lengthBuffer, payload]), deno.stdin);
    deno.stdin.end();
    
    // Deno端
    const decoder = new TextDecoder();
    const lengthLine = await Deno.readTextLine(Deno.stdin);
    const dataLength = parseInt(lengthLine, 10);
    const rawData = new Uint8Array(dataLength);
    await Deno.readFull(Deno.stdin, rawData);
    const jsonData = JSON.parse(decoder.decode(rawData));
    

内容的提问来源于stack exchange,提问作者Jaron

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 02:36:15