Promiseによる非同期処理のキャンセル機能を実装する

javascript, UXP

今後UXPの実装が進むとAdobe用のscriptの開発でこれまで以上に非同期処理が重要になるでしょう。もちろん非同期処理自体もはや当たり前のように使われていますが意外にキャンセルボタンの実装をしようと思ったかなりややこしかったのでまとめることにしました。なお、実装にあたってはこちらの記事を参考にしました。キャンセル可能でPromiseなsetTimeout()を作る

最初にPromise関数の実装にあたってPromiseの状態をオブジェクトで管理して一度resolve,rejectの結果を投げるメソッドをプロパティーに代入するという形をとっています。キャンセルボタンされない場合そのまま非同期が終わるまで実行。キャンセルされた場合はrejectを実行してエラーを投げる、という具合です。以下そのコード。

ボタンで実装する前に分かりやすくsetTimeoutで実装しました。同期オブジェクトはresolve,rejectメソッドをオブジェクトのプロパティーに代入してエラーの場合rejectが実行されるrejectsメソッドを実行します。スコープの外でキャンセル変数を宣言して非同期処理実行前にこのキャンセルメソッドを変数に代入。非同期メソッドはtry,catchで囲ってキャンセル、またはエラーがでたら処理を中断するようにします。キャンセルメソッドをコメントアウトしたり実行させたりすると非同期処理を実行させたりキャンセルする事ができます。ここまでできたら実際に何かしらのUI上でのボタンとしての実装も簡単ではないでしょうか。

例によってまたReactですが非同期処理のオブジェクトをuseStateで状態管理してます。(面倒でもuseStateで管理しないと上手くいかなかった。)キャンセルボタンが押されたらキャンセル用のメソッドが実行されてPromise処理が中止されるようになっています。Promiseが終わった時、もしくは中断された後にオブジェクトの状態を初期化するようにinitメソッドを実行。また非同期処理が実行されているか否かの状態をuseStateのcount変数で管理。非同期処理中には“counting”と表示してそれ以外の時は“waiting you click”を表示するようにしています。実際の実装の様子はこちらから。

ちなみに配列型の値を直列処理で非同期処理しつつキャンセル処理も実装したい場合は以下のようになります。

for文が実行されている途中でキャンセルメソッドの変数を代入し直してキャンセルされたらbreakで抜けるようにしています。

次回はプログレスバーの実装を書く予定です。

Beer 寄付してサイトを応援する。