0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AbortControllerを使って安全なsleepを実現したい

Posted at

実現したいこと

wait中にプログラムがシグナル(SIGINT/SIGTERM)を受信した場合に、速やかにタイマーを解除したい。ただし、タイマー強制解除は例外として受け取ることで、終了処理を書けるようにしたい。

コード

class ProcessMonitor {
    protected readonly abortController = new AbortController()

    constructor() {
        process.on("SIGINT", () => {
            this.abortController.abort();
        });
        process.on("SIGTERM", () => {
            this.abortController.abort();
        });
    }

    async wait(ms: number) {
        const {signal} = this.abortController
        signal.throwIfAborted()
        await new Promise<void>((resolve, reject) => {
            const type = "abort"
            const listener = () => {
                // setTimeout was aborted
                signal.removeEventListener(type, listener)
                reject(new DOMException("Aborted during wait", "AbortError"))
            }
            signal.addEventListener(type, listener);
            // Call setTimeout with signal. Callback won't be fired when signalled.
            setTimeout(() => {
                // setTimeout was not aborted.
                signal.removeEventListener(type, listener)
                resolve()
            }, ms, {signal})
        })
    }

    get isTerminating() {
        return this.abortController.signal.aborted
    }

    get isRunning() {
        return !this.isTerminating
    }
}

利用例

こちらの記事を書いているときに思いついたテクニックです。
https://qiita.com/tomohisaota/items/8900c96d299f4a02edf3

    async run() {
        this.isRunning = true
        try {
            while (processMonitor.isRunning) {
                this.count++
                if (this.count >= this.max) {
                    break
                }
                this.setNeedsUpdate()
                await processMonitor.wait(this.interval)
            }
        } catch (e) {
            if (e instanceof DOMException) {
                if (e.name === "AbortError") {
                    return
                }
            }
            throw e
        }
        this.isRunning = false
        this.isCompleted = true
        this.setNeedsUpdate()
    }

希望者がいればもう少し詳しく解説します。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?