跳到主要内容

node 工具链

execa

安装

npm install execa

回调接口

import { execa } from "execa";
// 除名字不一样, 其余与 spawn 一模一样
const cp = execa("echo", ["unicorns"]);
// ...

promise 接口

import { execa } from "execa";
// 参数和 spawsn 一模一样
// stdout 正常输出
// stderr 异常输出
// exitCode 退出编码
// failed 是否运行失败
// timedOut 是否超时
// killed 是否被杀死
const { stdout, stderr, exitCode, failed, timedOut, killed } = await execa(
"echo",
["unicorns"]
);

命令行

import { $ } from "execa";

const branch = await $`git branch --show-current`;

node-fetch

安装

pnpm add node-fetch

基本使用

  • 同 fetch;

stream 相关

基础

  • node-fetch 中 body 与 fetch 不同;
  • 为 Readable stream;

读取 body

import { createWriteStream } from "node:fs";
import { pipeline } from "node:stream";
import { promisify } from "node:util";
import fetch from "node-fetch";

const streamPipeline = promisify(pipeline);
const response = await fetch(
"https://github.githubassets.com/images/modules/logos_page/Octocat.png"
);
await streamPipeline(response.body, createWriteStream("./octocat.png"));

写入 body

Blob
import fetch, {
Blob,
blobFrom,
blobFromSync,
File,
fileFrom,
fileFromSync,
} from "node-fetch";

const mimetype = "text/plain";
const blob = fileFromSync("./input.txt", mimetype);
const url = "https://httpbin.org/post";
const response = await fetch(url, { method: "POST", body: blob });
const data = await response.json();
File
import fetch, { FormData, File, fileFrom } from "node-fetch";

const httpbin = "https://httpbin.org/post";
const formData = new FormData();
const binary = new Uint8Array([97, 98, 99]);
const abc = new File([binary], "abc.txt", { type: "text/plain" });
formData.set("greeting", "Hello, world!");
formData.set("file-upload", abc, "new name.txt");

const response = await fetch(httpbin, { method: "POST", body: formData });
const data = await response.json();

差异

  • res.body 为 Readable stream;
  • 仅支持 text()/json()/blob()/arraybuffer()/buffer();
  • 没有实现服务器端 cookie 状态管理;
  • 无法使用 bodyUsed;

cfork

安装

pnpm add cfork --save-dev

基础使用

const cfork = require("cfork");
const util = require("util");

cfork({
exec: "/your/app/worker.js",
})
.on("fork", (worker) => {
console.warn(
"[%s] [worker:%d] new worker start",
Date(),
worker.process.pid
);
})
.on("disconnect", (worker) => {
console.warn(
"[%s] [master:%s] wroker:%s disconnect, exitedAfterDisconnect: %s, state: %s.",
Date(),
process.pid,
worker.process.pid,
worker.exitedAfterDisconnect,
worker.state
);
})
.on("exit", (worker, code, signal) => {
const exitCode = worker.process.exitCode;
const err = new Error(
util.format(
"worker %s died (code: %s, signal: %s, exitedAfterDisconnect: %s, state: %s)",
worker.process.pid,
exitCode,
signal,
worker.exitedAfterDisconnect,
worker.state
)
);
err.name = "WorkerDiedError";
console.error(
"[%s] [master:%s] wroker exit: %s",
Date(),
process.pid,
err.stack
);
})
// if you do not listen to this event
// cfork will output this message to stderr
.on("unexpectedExit", (worker, code, signal) => {
// logger what you want
})
// emit when reach refork times limit
.on("reachReforkLimit", () => {
// do what you want
});

// if you do not listen to this event
// cfork will listen it and output the error message to stderr
process.on("uncaughtException", (err) => {
// do what you want
});

选项

  • exec :exec file path;
  • slaves :slave process config;
  • args :exec arguments;
  • count :fork worker nums,default is os.cpus().length;
  • refork :refork when worker disconnect or unexpected exit,default is true;
  • limit:limit refork times within the duration,default is 60;
  • duration:default is 60000,one minute (so,the refork times < limit / duration);
  • autoCoverage:auto fork with istanbul when running_under_istanbul env set,default is false;
  • env:attach some environment variable key-value pairs to the worker / slave process,default to an empty object;
  • windowsHide:Hide the forked processes console window that would normally be created on Windows systems,default to false;
  • serialization:Specify the kind of serialization used for sending messages between processes.Possible values are 'json' and 'advanced'.See Advanced serialization for child_process for more details.Default:false;