node.js - Asynkron child_process.exec med TypeScript
Jag försöker använda ett child_process.exec-anrop med TypeScript, och felhantering verkar vara extremt svårt att få rätt.
Här är kärnan i vad jag försöker göra:
import { promisify } from "util";
import { exec, ExecException } from "child_process";
const execPromise = promisify(exec);
export const myCommand = async (param: string) => {
const { stdout, stderr } = await execPromise(`my_command ${param}`);
return {
stdout,
stderr,
// some other fields
};
};
Detta fungerar bra så länge my_command returnerar 0.
Nu kan my_command ibland returnera 1, men det borde vara ett fel, inte ett undantag. Det är ganska normalt och jag vill hantera det. Med promisify blir det dock ett undantag, så jag försökte hantera det på detta sätt:
let stdout, stderr: string;
try {
const { stdout: execStdout, stderr: execStderr } = await execPromise(`my_command ${param}`);
stdout = execStdout;
stderr = execStderr;
} catch (e: unknown) {
// ???
}
Här är vad jag försökte för undantagshantering:
if (e instanceof ExecException) {}
men det misslyckas med 'ExecException' refererar endast till en typ, men används här som ett värde.
Jag försökte också:
if ("stdout" in e) {}
eftersom jag vill hämta stdout från felet men det misslyckas med Object is of type 'unknown'..
Jag försökte sedan tvinga en typ påståelse med:
e as ExecException
Det fungerar på ett sätt men:
- det är riskabelt
- Jag märkte att ExecException inte har fälten
stdout/stderrsom den borde ha, så jag kan fortfarande inte få dem vid fel, vilket inte alls är logiskt...
Så jag är lite osäker på vad jag ska göra. Kan någon hjälpa mig?
Svar #1
Du kan definiera en typvakt:
function isStdError(err: any): err is { stderr: string } {
return !!err.stderr
}
Sedan i din kod:
try {
await exec(`my_command`)
} catch (e) {
if (isStdError(e)) {
console.log(e.stderr)
} else {
throw e
}
}
