微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

节点 - 以类形式编写子进程 spawn 执行

如何解决节点 - 以类形式编写子进程 spawn 执行

我正在重写一个现有的模块,它会产生一个子进程并执行一个命令。

我已经将它重新编写为一个类,但是当我运行代码时,我收到一个错误提示 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.resolvehandlers.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 传递给它们,因为它已经在它们内部可用。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。