问题描述
我正在重写一个现有的模块,它会产生一个子进程并执行一个命令。
我已经将它重新编写为一个类,但是当我运行代码时,我收到一个错误,提示 Promise 拒绝并解决未定义。
我假设我错误地将它们传递给 .call
方法,但我没有找到可以传递它们的不同方式。
代码如下:
import logger from './logger.utils';
import { spawn,ChildProcess } from 'child_process';
/**
* This function runs a spawn command and rejects the promise if timed out
* @param cmd - the command to execute
* @param params - the command's parameters
* @param timeoutMs - timeout in milliseconds
* @param taskDescription - a text description of the task for logging
*/
export class SpawnTimeout {
cmd: string;
params: string[];
finished: boolean;
childProcess: ChildProcess;
timeoutMs: number;
timeout: NodeJS.Timeout;
taskDescription: string;
handlers: Object;
constructor(
cmd: string,params: string[],timeoutMs: number,taskDescription: string = 'no description specified'
) {
this.finished = false;
this.childProcess = spawn(cmd,params,{
stdio: [process.stdin,process.stdout,process.stderr],});
this.timeoutMs = timeoutMs;
this.timeout = null;
this.taskDescription = taskDescription;
this.cmd = cmd;
this.params = params;
}
exec() {
return new Promise((resolve,reject) => {
const handlers = {
resolve,reject,};
this.handlers = handlers;
this.childProcess.once('error',this._onError.call(this.handlers));
this.childProcess.once('exit',this._onExit.call(this.handlers));
this.timeout = setTimeout(this._setTimeout,this.timeoutMs);
});
}
_onError(err: Error,handlers) {
clearTimeout(this.timeout);
const message = `spawn [${this.taskDescription}] ${this.cmd},${this.params} Failed with error ${err}`;
logger.error(message);
handlers.reject(new Error(message));
}
_onExit(code: number,handlers) {
this.finished = true;
clearTimeout(this.timeout);
logger.debug(`spawn [${this.taskDescription}] finished.code ${code}`);
if (code == 0) {
handlers.resolve(true);
}
// case of error,code !== 0
const message = `spawn [${this.taskDescription}] cmd : ${this.cmd} ${this.params}. Failed with code ${code}`;
logger.error(message);
handlers.reject(new Error(message));
}
_setTimeout() {
if (!this.finished) {
logger.warn(
`spawn [${this.taskDescription}] - timeout. cmd : ${this.cmd},${this.params}`
);
this.childProcess.kill();
}
}
}
调用 handlers.resolve
或 handlers.reject
时会产生错误。
请告诉我如何解决这个问题?或者即使这样的实施良好实践。
解决方法
call
立即调用一个函数,第一个参数是 this
调用函数的上下文,在这种情况下它不返回函数并且将结果作为侦听器提供是不正确的once
。
回调需要用一个函数包装以提供预期的参数:
this.childProcess.once('error',err => this._onError(err,this.handlers))
this.childProcess.once('exit',code => this._onExit(code,this.handlers));
由于回调必须以这种方式纠正 this
,因此可能没有必要将 this.handlers
传递给它们,因为它已经在它们内部可用。