2
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?

More than 1 year has passed since last update.

CancelablePromise を自前で作るのはやめておいたほうがいいのでは

Posted at

世の JavaScript エンジニアは一度は考えることではないかと思うけども。

JavaScript の Promise には処理を途中でキャンセルする API は無いので、キャンセルできるようにする Promise を考えた。

class CancelablePromise extends Promise {
    #reject = null

    constructor(executor) {
        let _reject = undefined
        super((resolve, reject) => {
            _reject = reject
            return executor(resolve, reject)
        })
        this.#reject = _reject
    }

    cancel(reason) {
        this.#reject(reason)
    }
}

普通の Promise に cancel メソッドを生やして、外部からでも呼べるようにした。

const promise = new CancelablePromise((resolve, reject) => { /* 非同期処理 */ })

// キャンセルする
promise.cancel()

動かしてみると、一見ちゃんと動いているように見える。

しかし、
よくみると処理そのものは止まっていない。

例えばこういう非同期関数を用意する。

// 10秒後に resolve する非同期関数
function wait10sec() {
  return new CancelablePromise((resolve, reject) => {
    let timer = 10 + 1
    const id = window.setInterval(() => {
      console.log(--timer)
      if (timer === 0) {
        window.clearInterval(id)
        resolve()
      }
    }, 1000)
  })
}

10秒後に完了する非同期関数を実行して、5秒後にキャンセルしてみる。

const promise = wait10sec()
  .then(() => console.log("Yay"))
  .catch(() => console.log("Oops"))

// 5秒後にキャンセルする
window.setTimeout(() => promise.cancel(), 5000)

image.png

全然止まってない上に then にチェーンされとるやんけ!!

つまり Promise のステータスが rejected になるだけで、非同期処理そのものを停止できるわけではない、と。(then にチェーンされたのは何故なのか不明)

一度実行した非同期処理を止めるのは無理では?と思っているのですがどうなのでしょうかね。
有識者の方はコメントいただけるとありがたいです。

2
0
1

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
2
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?