在命中 API 端点时运行脚本,并在再次命中时检查该脚本是否正在运行 - Node.js

分享于2022年07月17日 child-process cron javascript node.js process 问答
【问题标题】:在命中 API 端点时运行脚本,并在再次命中时检查该脚本是否正在运行 - Node.js(Run a script when API endpoint is hit, and check if that script is running when hit again - Node.js)
【发布时间】:2022-01-26 14:47:51
【问题描述】:

我正在开发一个 node.js API,当某个端点被命中时,它需要启动/运行一个耗时的 javaScript 文件。我已经完成了这项工作,但是我现在正在寻找一种方法来阻止脚本再次运行,如果它已经在运行并且端点再次被命中。

我尝试使用 child_process 库,希望如果脚本作为与主 node.js 应用程序分开的进程执行,则更容易检查脚本是否已经在运行。我曾想过为我创建的子进程使用 process exit 事件,但事实证明这没有用,因为它只会在进程完成后运行,但无助于检查它当前是否正在运行。

我也考虑过 cron 作业,但似乎没有一个好方法可以在不制定基于时间的计划的情况下根据命令启动 cron 作业。

在另一个项目中,我使用了一个数据库并简单地在表中创建了一个新行来指示脚本是否可以运行、当前正在运行或已完成。我绝对可以再次这样做,但我正在努力让这个项目尽可能轻松。

最后,我确实考虑过添加一些全局状态变量来指示进程是否正在运行,但不确定这是否是最好的方法。

因此,如果有人知道一种方法来检查子进程脚本当前是否正在运行,或者有更好的方法来实现我在这里尝试实现的目标,那么任何方向都会有所帮助。

  • 作者在 MineOS 中找到了 Minecraft 的 Java 实例。看起来他跟踪每个实例的进程 ID 并检查它是否存在。类似于你的全局变量想法。

【解决方案1】:

你可以使用一个变量,它甚至不必是全局的!

class MySingletonProcess {
  constructor() {
    this.isBusy = false;
    this.spawnProcess = this.spawnProcess.bind(this);
  }

  doProcess() {
    console.log("Doing process...");
    // fake async stuff...
    return new Promise((resolve) => {
      setTimeout(() => {
        this.isBusy = false;
        resolve();
      }, 2500);
    });
  }

  spawnProcess() {
    if (this.isBusy) {
      console.log("I'm busy!");
      return;
    } else {
      this.isBusy = true;
      this.doProcess();
    }
  }
}

const processSingleton = new MySingletonProcess();
const button = document.getElementById("button");
button.addEventListener("click", processSingleton.spawnProcess);
<button id="button">Click Me To Spawn Process</button>

  • 有趣。我可以将它添加为一个实用程序类,它在应用程序启动时被初始化,然后在启动进程的服务中访问。我会试一试,然后回复你。
  • 刚刚试用了您的解决方案,效果很好!我不得不在这里和那里更改一些东西以使用我当前的代码,但最终它是相同的想法。谢谢你的帮助!与我之前尝试过的其他方法相比,这种方法明显更简单、更有效。
  • 很高兴听到这个消息!