node js一个接一个执行python脚本

Node js execute python script one after the other

我有一个 React 应用程序,我想在单击按钮时一个接一个地使用 Node 执行多个脚本(可以是 N 个脚本)。我也有每个脚本的一些状态,所以当脚本完成时我想将他的状态设置为“完成”。

经过一些 google-ing 我最终得到了:

function runScript(command, args, options, id, callback) {
  const child = childProcess.spawn(command, args, options);

  child.stdout.on('data', (data) => {
    console.log(`${data}`);
  });

  child.stderr.on('data', (data) => {
    console.log(`${data}`);
  });

  // callback function to change the state to "completed"
  child.on('close', () => callback(id, 'completed'));
}

const deployScripts = () => {
    loadedSteps.forEach((script) => {
      if (script.path.length) {
        const [command, args, options] = getParamBasedOnFile(script.path);
        if (command) {
          //set the script to "active" which means is running
          updateStepStatus(script.id, 'active');
          runScript(command, args, options, script.id, updateStepStatus);
        }
      }
    });
  }; 

它有效,但当然因为它的异步是 运行 所有脚本同时运行,这不是我想要的。

然后我去尝试同步

function runScript(command, args, options) {
  const child = childProcess.spawnSync(command, args, options);

  console.log(child.stdout.toString());
  // callback(id, 'completed');  -> doesnt work
  console.log('exit run script function');
}

const deployScripts = () => {
    loadedSteps.forEach((script) => {
      if (script.path.length) {
        const [command, args, options] = getParamBasedOnFile(script.path);
        if (command) {
          updateStepStatus(script.id, 'active');
          runScript(command, args, options, script.id, updateStepStatus);
          updateStepStatus(script.id, 'completed');
        }
      }
    });
  };

但问题在于,即使它一个接一个地运行脚本(我可以在控制台中看到输出),两个脚本状态同时设置为“完成”(当我测试时它 1 python 脚本有 5 秒的睡眠,另一个有 10 秒的睡眠,所以第一个应该设置为完成,然后在 5 秒后第二个)。

不确定这样做的最佳方法是什么。

您可以承诺 runScript 并将一系列步骤实现为 async 函数,这样您就可以使用 await 等待每个步骤完成,然后再 运行 next步骤.

const childProcess = require("child_process")

/* mocks */

const loadedSteps = [{path:'foo', id:1}, {path:'bar', id:2}, {path:'baz', id:3}]

function getParamBasedOnFile(path) {
    return ['python', ['-c', "import time;time.sleep(1)"], {}]
}

function updateStepStatus(id, status) {
    console.log(id, status)
}

/* code */

function runScript(command, args, options) {
    return new Promise((resolve, reject) => {
        const child = childProcess.spawn(command, args, options);
        child.on('close', () => resolve(child.stdout.toString()))
    })
}

async function deployScripts() {
    for(const script of loadedSteps) {
        if (script.path.length) {
            const [command, args, options] = getParamBasedOnFile(script.path);
            if (command) {
                updateStepStatus(script.id, 'active');
                await runScript(command, args, options, script.id);
                updateStepStatus(script.id, 'completed');
            }
        }
    }
};

/* main */

deployScripts().then(() => console.log('done'))