Moonlit
Moonlit

Reputation: 5419

Stop periodic execution of function gracefully

In typescipt/nodejs, how can i gracefully shutdown a component that is repeatedly doing stuff. I.e., i want the user to be able to send SIGINT signal e.g. by hitting <ctrl+c> to stop the program gracefully:

export class Repeater {
  private running: boolean;

  constructor() {
    this.running = false;
  }

  public do(): void {
    this.running = true;
    setTimeout(() => {
      if (this.running) {
        // do stuff
        this.do();
      }
    }, 3000);
  }

  public stop(): void {
    this.running = false;
  }
}

Usage:

const repeater = new Repeater();
process.on("SIGINT", () => {
  repeater.stop();
  process.exit();
});

repeater.start();

I've started with the code above, however what is missing is the part where the call to stop() is actually blocking until the current execution of do() is finished?

Upvotes: 0

Views: 54

Answers (1)

jsejcksn
jsejcksn

Reputation: 33881

You can return a promise from the stop method, and exit the process after it resolves. Set it to resolve after the end of the interval when running is no longer true:

You referenced a start method that you didn't show, so I created one in the code below.

TS Playground

export class Repeater {
  private running: boolean = false;
  private finalize: () => void = () => {};
  private done: Promise<void> = new Promise(resolve => this.finalize = resolve);

  public do(): void {
    // do stuff

    setTimeout(() => {
      if (this.running) this.do();
      else this.finalize();
    }, 3000);
  }

  public start(): void {
    if (!this.running) {
      this.running = true;
      this.done = new Promise(resolve => this.finalize = resolve);
      this.do();
    }
  }

  public stop(): Promise<void> {
    this.running = false;
    return this.done;
  }
}

const repeater = new Repeater();

process.on("SIGINT", () => {
  repeater.stop().then(() => process.exit());
});

repeater.start();

Upvotes: 1

Related Questions