世の 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)
全然止まってない上に then
にチェーンされとるやんけ!!
つまり Promise のステータスが rejected になるだけで、非同期処理そのものを停止できるわけではない、と。(then にチェーンされたのは何故なのか不明)
一度実行した非同期処理を止めるのは無理では?と思っているのですがどうなのでしょうかね。
有識者の方はコメントいただけるとありがたいです。