Adobe UXP Promiseエラーをログに書いてくれない
Promise、ECMA2015移行のJSを学ぶ上で一つの壁ですがUXPでのこのPromiseの仕様が問題になっています。
エラーを返さない
以下のコードはfalseを引数に渡すとエラーを返すだけのPromise関数です。これをブラウザとか、Node.jsなどの環境下でfalseを渡して実行してみます。
結果はエラーを返すでしょう。当たり前ですしエラー処理を想定していない場合はPromiseの関数以下にコードが書いてあっても実行されません。
ただconsoleにエラーが起きているか知らせてくれるので何が原因かすぐにわかるので修正はしやすいです。問題はこれをUXP上で実行してみます。そして何もconsole上に表示されないと思います。
エラーをログに書いてくれない
UXP環境下で開発していると薄々気づくと思うのですが何かエラーを表示してくれないことが多々あります。ぱっと見何も問題なさそうに見えて実は何処かで処理が止まっている、その原因の一つがPromise内のエラーをconsoleにログとして書いてくれないことです。これの何が問題かというとPhotoshopのAPIは基本全て非同期処理なのでPhotoshop関係の処理はコード内に問題があって止まってもconsoleに表示されない以上エラーが起きていることすらわからず原因解明に時間がかかってしまうことです。例えば以下のコード
なんの変哲もないレイヤーを作成するコードです。勿論ドキュメントを開かれている時に実行すればレイヤーが作成されますがドキュメントを開いていないときに実行しても何も動きません。勿論そういう時には内部ではエラーが起きているのですがUXPの場合見た目から判別できません。これを対策する場合は以下のようにします。
try catchで囲めばとりあえず捕捉はできます。当たり前のようですが逆に全てのPromise内の関数をtry catchで囲まないと思いがけないエラーが出た時にどこで何が起こっているかわからりません。しかもこのexecuteAsModalというのはさらに厄介でコールバック関数内で囲まないとエラーが捕捉されません。
というわけで全てのPhotoshopのexecuteAsModalスコープは面倒でも必ずtry catchでコールバック内のコードを囲む必要があります。
解決策
解決策らしい解決策は無いのですがコミュニティにとりあえずの回避策が提示されています。Promiseの関数をtry catchスコープで囲むカリー化された関数です。
一応エラーの捕捉はできますが一々全てのPromiseを返す関数をカリー化関数にいちいち渡さないといけません。コミュニティでも触れられていますがこれが非同期関数200とか300もあるコードになると流石に大きな負担になります。それでも公式からの回答がこれなので他に代替があるわけでもなさそうです。
executeAsModalも含めて囲む
executeAsModalスコープはPhotoshopにアクセスするAPIを実行する上でこのスコープ内で実行するのが必須なので今回これも含めて凡庸的な関数を作ってみたいと思いました。
executeAsModalをPromiseで囲っているのはexecuteAsModal自体コールバックを実行する関数なのでPhotoshopへの処理を実行後にパネル側に値を持っていきたい場合などresolveで受け取らないとexecuteAsModalスコープ外に持ち込めません。さらにexecuteAsModal内をtry、catchで囲んでエラーも捕捉できるようにしています。executionContextは引数の関数で受け取るようにしないとPhotoshopの関数内でexecutionContext関係の処理が行えません。他にいい方法があれば教えてください。
またこれに限らずwebの環境との違いでバグに引っかかる箇所が多いので違和感を感じたらUXP自体の仕様と違いがないか何度も確認するのをお勧めします。最後に参考リンクのコミュニティのやりとりの内容を読むとさらに深くこの事について知れるでしょう。