노드의 child_process를 약속하는 방법.exec 및 child_process.Bluebird에서 execFile 기능을 사용하시겠습니까?
Node.js 아래에 있는 Bluebird promise 라이브러리를 사용하고 있습니다. 좋습니다!하지만 질문이 있습니다.
노드의 child_process에 대한 문서를 보면,exec 및 child_process.execFile 이 두 함수 모두 ChildProcess 개체를 반환하는 것을 볼 수 있습니다.
그렇다면 이러한 기능을 약속하는 권장 방법은 무엇일까요?
다음이 작동합니다(I get a Promise 개체).
var Promise = require('bluebird');
var execAsync = Promise.promisify(require('child_process').exec);
var execFileAsync = Promise.promisify(require('child_process').execFile);
그러나 원래 Node.js 함수의 원래 반환 값에 액세스하려면 어떻게 해야 합니까?(이 경우 원래 반환된 ChildProcess 개체에 액세스할 수 있어야 합니다.)
어떤 제안이든 감사하겠습니다!
편집:
다음은 child_process의 반환 값을 사용하는 예제 코드입니다.exec 함수:
var exec = require('child_process').exec;
var child = exec('node ./commands/server.js');
child.stdout.on('data', function(data) {
console.log('stdout: ' + data);
});
child.stderr.on('data', function(data) {
console.log('stderr: ' + data);
});
child.on('close', function(code) {
console.log('closing code: ' + code);
});
그러나 약속된 버전의 exec 함수(위의 execAsync)를 사용하면 반환 값은 ChildProcess 개체가 아닌 약속 값이 됩니다.이것이 제가 말하는 진짜 문제입니다.
Bluebird와 같은 추가 라이브러리 종속성보다 언어에 내장된 표준 JS 약속을 사용하는 것이 좋습니다.
Node 10+를 사용하는 경우 Node.js 문서는 다음을 사용할 것을 권장합니다.util.promisify
이것은 a를 반환합니다.Promise<{ stdout, stderr }>
물건.아래 예를 참조하십시오.
const util = require('util');
const exec = util.promisify(require('child_process').exec);
async function lsExample() {
try {
const { stdout, stderr } = await exec('ls');
console.log('stdout:', stdout);
console.log('stderr:', stderr);
} catch (e) {
console.error(e); // should contain code (exit code) and signal (that caused the termination).
}
}
lsExample()
오류를 먼저 처리합니다.stderr
.
통화 내용에서 두 가지를 반환하려는 것처럼 들립니다.
- 아동 과정
- 하위 프로세스가 완료되면 해결되는 약속
그렇다면 "이러한 기능을 약속하는 권장 방법"은 무엇입니까?하지 마
당신은 컨벤션 밖에 있습니다.약속 반환 함수는 약속을 반환할 것으로 예상되며, 이것으로 끝입니다.두 멤버(Child Process & the promise)가 포함된 개체를 반환할 수 있지만, 이는 사람들을 혼란스럽게 할 뿐입니다.
약속되지 않은 함수를 호출하고 반환된 childProcess를 기반으로 약속을 만드는 것을 제안합니다.(도움말 기능으로 포장할 수 있음)
이런 식으로 하면, 코드를 읽는 다음 사람에게는 상당히 명백합니다.
다음과 같은 것:
var Promise = require('bluebird');
var exec = require('child_process').execFile;
function promiseFromChildProcess(child) {
return new Promise(function (resolve, reject) {
child.addListener("error", reject);
child.addListener("exit", resolve);
});
}
var child = exec('ls');
promiseFromChildProcess(child).then(function (result) {
console.log('promise complete: ' + result);
}, function (err) {
console.log('promise rejected: ' + err);
});
child.stdout.on('data', function (data) {
console.log('stdout: ' + data);
});
child.stderr.on('data', function (data) {
console.log('stderr: ' + data);
});
child.on('close', function (code) {
console.log('closing code: ' + code);
});
만약 당신이 단지 약속을 하고 싶은 말은child_process.exec()
그리고.child_process.execFile()
최근 노드 버전에서는 여기에 더 나은 답변이 있습니다.
Node v12 이후로 기본 제공util.promisify
에 대한 액세스를 허용합니다.ChildProcess
된 환된객에 Promise
인증되지 않은 호출에 의해 반환될 수 있는 내장 함수의 경우.문서에서:
된 돌온사들람.
ChildProcess
는 스에있습어다니되에 .Promise
child
소유물.
이를 통해 정확하고 간단하게 액세스할 수 있습니다.ChildProcess
Node v12+를 사용할 수 있는 경우에는 원래 질문에서 다른 답변을 사용할 수 없습니다.
질문자가 제공한 예제(그리고 간결한 스타일)를 적용하여 접근ChildProcess
다음과 같이 달성할 수 있습니다.
const util = require('util');
const exec = util.promisify(require('child_process').exec);
const promise = exec('node ./commands/server.js');
const child = promise.child;
child.stdout.on('data', function(data) {
console.log('stdout: ' + data);
});
child.stderr.on('data', function(data) {
console.log('stderr: ' + data);
});
child.on('close', function(code) {
console.log('closing code: ' + code);
});
// i.e. can then await for promisified exec call to complete
const { stdout, stderr } = await promise;
다른 방법이 있습니다.
function execPromise(command) {
return new Promise(function(resolve, reject) {
exec(command, (error, stdout, stderr) => {
if (error) {
reject(error);
return;
}
resolve(stdout.trim());
});
});
}
다음 기능을 사용합니다.
execPromise(command).then(function(result) {
console.log(result);
}).catch(function(e) {
console.error(e.message);
});
또는 비동기/대기의 경우:
try {
var result = await execPromise(command);
} catch (e) {
console.error(e.message);
}
모든 사용 사례를 완벽하게 처리할 수 있는 방법은 아마 없을 것입니다.그러나 제한적인 경우 다음과 같은 작업을 수행할 수 있습니다.
/**
* Promisified child_process.exec
*
* @param cmd
* @param opts See child_process.exec node docs
* @param {stream.Writable} opts.stdout If defined, child process stdout will be piped to it.
* @param {stream.Writable} opts.stderr If defined, child process stderr will be piped to it.
*
* @returns {Promise<{ stdout: string, stderr: stderr }>}
*/
function execp(cmd, opts) {
opts || (opts = {});
return new Promise((resolve, reject) => {
const child = exec(cmd, opts,
(err, stdout, stderr) => err ? reject(err) : resolve({
stdout: stdout,
stderr: stderr
}));
if (opts.stdout) {
child.stdout.pipe(opts.stdout);
}
if (opts.stderr) {
child.stderr.pipe(opts.stderr);
}
});
}
이것은 허용됩니다.opts.stdout
그리고.opts.stderr
자식 프로세스에서 stdio를 캡처할 수 있도록 인수를 지정합니다.
예:
execp('ls ./', {
stdout: new stream.Writable({
write: (chunk, enc, next) => {
console.log(chunk.toString(enc));
next();
}
}),
stderr: new stream.Writable({
write: (chunk, enc, next) => {
console.error(chunk.toString(enc));
next();
}
})
}).then(() => console.log('done!'));
간단히 말하면:
execp('ls ./', {
stdout: process.stdout,
stderr: process.stderr
}).then(() => console.log('done!'));
여러분의 문제를 완벽하게 해결할 수 있는 좋은 도구가 있다는 것을 말씀드리고 싶습니다.
https://www.npmjs.com/package/core-worker
이 패키지를 사용하면 프로세스를 훨씬 쉽게 처리할 수 있습니다.
import { process } from "CoreWorker";
import fs from "fs";
const result = await process("node Server.js", "Server is ready.").ready(1000);
const result = await process("cp path/to/file /newLocation/newFile").death();
또는 다음 기능을 결합합니다.
import { process } from "core-worker";
const simpleChat = process("node chat.js", "Chat ready");
setTimeout(() => simpleChat.kill(), 360000); // wait an hour and close the chat
simpleChat.ready(500)
.then(console.log.bind(console, "You are now able to send messages."))
.then(::simpleChat.death)
.then(console.log.bind(console, "Chat closed"))
.catch(() => /* handle err */);
다른 예로 동일한 const를 사용하여 파괴할 때 여러 명령을 실행할 때 문제가 발생할 수 있습니다. 이렇게 이름을 바꿀 수 있습니다.
const util = require('util');
const exec = util.promisify(require('child_process').exec);
async function runCommands() {
try {
const { stdout, stderr } = await exec('ls');
console.log('stdout:', stdout);
console.log('stderr:', stderr);
const { stdout: stdoutTwo, stderr: stderrTwo } = await exec('ls');
console.log('stdoutTwo:', stdoutTwo);
console.log('stderrTwo:', stderrTwo);
const { stdout: stdoutThree, stderr: stderrThree } = await exec('ls');
console.log('stdoutThree:', stdoutThree);
console.log('stderrThree:', stderrThree);
} catch (e) {
console.error(e); // should contain code (exit code) and signal (that caused the termination).
}
}
runCommands()
여기 제 2센트입니다.출력을 스트리밍하고 쓰기 작업을 수행하는 sna를 사용합니다.stdout
그리고.stderr
오류 및 표준 출력은 버퍼에 캡처되어 반환되거나 거부됩니다.
이것은 I Types 스크립트로 작성되었습니다. JavaScript를 사용하는 경우에는 자유롭게 타이핑을 제거하십시오.
import { spawn, SpawnOptionsWithoutStdio } from 'child_process'
const spawnAsync = async (
command: string,
options?: SpawnOptionsWithoutStdio
) =>
new Promise<Buffer>((resolve, reject) => {
const [spawnCommand, ...args] = command.split(/\s+/);
const spawnProcess = spawn(spawnCommand, args, options);
const chunks: Buffer[] = [];
const errorChunks: Buffer[] = [];
spawnProcess.stdout.on("data", (data) => {
process.stdout.write(data.toString());
chunks.push(data);
});
spawnProcess.stderr.on("data", (data) => {
process.stderr.write(data.toString());
errorChunks.push(data);
});
spawnProcess.on("error", (error) => {
reject(error);
});
spawnProcess.on("close", (code) => {
if (code === 1) {
reject(Buffer.concat(errorChunks).toString());
return;
}
resolve(Buffer.concat(chunks));
});
});
제 것은 여기 있어요.stdin이나 stdout은 다루지 않으므로, 필요하다면 이 페이지의 다른 답변 중 하나를 사용하십시오.:)
// promisify `child_process`
// This is a very nice trick :-)
this.promiseFromChildProcess = function (child) {
return new Promise((resolve, reject) => {
child.addListener('error', (code, signal) => {
console.log('ChildProcess error', code, signal);
reject(code);
});
child.addListener('exit', (code, signal) => {
if (code === 0) {
resolve(code);
} else {
console.log('ChildProcess error', code, signal);
reject(code);
}
});
});
};
언급URL : https://stackoverflow.com/questions/30763496/how-to-promisify-nodes-child-process-exec-and-child-process-execfile-functions
'programing' 카테고리의 다른 글
파이썬 및 MySQL (0) | 2023.07.26 |
---|---|
Hibernate가 생성된 쿼리에서 사용하는 SQL 테이블 별칭을 제어하려면 어떻게 해야 합니까? (0) | 2023.07.26 |
오류: '노드'에서 'appendChild'를 실행하지 못했습니다. 매개 변수 1이 '노드' 유형이 아닙니다. (0) | 2023.07.26 |
예외 없이 트랜잭션 롤백을 수행하시겠습니까? (0) | 2023.07.26 |
Python 개체에 대한 복사/딥 복사 작업을 재정의하는 방법은 무엇입니까? (0) | 2023.07.26 |