LoginSignup
0
0

More than 1 year has passed since last update.

[OutSystems]JavaScript要素で発生した例外の扱い

Last updated at Posted at 2022-09-23

Reactive Web App/Mobileでは、Client Action内でJavaScript要素を配置することで、JavaScriptのコードを記述できる。
では、そのJavaScript要素内で例外が発生して、JavaScript要素外に波及したとき(JavaScript要素内で処理されなかったとき)どうなるかを確認してみる。

環境

Personal Environment(Version 11.17.0 (Build 36291))
Service Studio(Version 11.53.17)

サンプル

Forgeコンポーネント: HousesoftSampleReactiveのV1.0.12。

モジュール > MainFlow > Exception Screenの「③JavaScript要素で発生した例外の処理」下にある各ボタン

結果のまとめ

  • JavaScript要素内で発生した例外が未処理だと、ローコード部分(Action Flow)ではAll Exceptionsで処理することになる
  • よって、JavaScriptで発生する例外処理をGlobal Exception Handlerに任せるのでなければJavaScript内で行うことを考える。その際、JavaScript APIのLogger.errorでService Centerのエラーログに記録できる
  • JavaScriptから非同期のClient Actionを呼んだときは、その内部で例外が起きるとAll ExceptionsでもHandleできないため、thenの第2引数(onRejectedコールバック関数)またはcatchで適切に処理する

1. JavaScript要素で発生した例外をcatchしなかった場合

まず基本を確認すると、Client Action内にJavaScriptを書くには、Action Flow内に要素を配置する。
image.png

配置した要素をダブルクリックするとエディタが開くので、JavaScriptのコードを記述する。

ここでは、JavaScript要素でcatchされない例外を発生させたいので、以下のように記述してみる。

throw("throw an exception from inside of JavaScript element: test");

このとき、ローコード部分では、All ExceptionsのException HandlerでHandleできる。

2. JavaScript要素で発生した例外をOutSystemsのエラーログに記録するには

OutSystemsにはエラーログの仕組みが組み込みで備わっている。JavaScriptで発生したエラーについても同じ仕組みで記録したい。

この目的には、JavaScript API - LoggerのBuilt-in Functionであるerrorが使える。

この関数に渡したメッセージは、console.logとService Center両方に出力される。
例外をcatchしたら、Logger.errorを呼べば良い。

try {
    throw("throw an exception from inside of JavaScript element: test");
} catch (ex) {
    $public.Logger.error($public.ApplicationContext.getCurrentContext().moduleName,
                         "Logger.errorで出力", ex);
}

出力例
image.png

3. 非同期のJavaScriptから例外

JavaScript内で\$resolve/$rejectという関数を呼んだ場合、そのClient Actionは非同期の扱いになる。
詳細はOutsystemsで非同期処理を実装する方法(Promiseを使う方法)を参照。

ここでは、以下のようにJavaScript要素の直後にMessage要素、また同じAction Flow内に各種Exceptionに対するHandlerを配置し、①JavaScript要素後も処理が継続するか②throwした例外がローコードでHandleされるか を確認する。
image.png

3.1 非同期JavaScriptから例外をthrow

JavaScriptのコード。コード中に\$resolve呼び出しがあるので非同期の扱いになるが、\$resolveの手前に例外のthrowがあるので実行は例外で中断する。

$parameters.Out1 = "正常終了";
throw("throw an exception from inside of JavaScript element: test");
$resolve();

この場合、All ExceptionsのException Handlerで捕捉できる。

3.2 thenのコールバックから例外をthrowした場合

別の非同期Client ActionをJavaScriptで呼び($actions.を経由)、そのコールバック(then関数の第1引数で指定)中でthrowを使って例外を発生させた場合。

以下のサンプルコードでは、thenの第2引数は実際には到達しない。
$actions.AsynchronousClientAction()で呼び出しているAsynchronousClientActionは、非同期のJavaScript要素を配置したClient Action呼び出し。

$actions.AsynchronousClientAction().then(function(result) {
  $parameters.Out1 = "正常終了";
  throw("throw an exception from inside of then callback: test");
  $resolve();
}, function (error) {
  throw("rethrow: " + error);
});

AsynchronousClientAction Action内のJavaScript
$parameters.Out1 = "正常終了";
$resolve();

この場合、ローコードのException Handlerには引っかからない。

3.3 非同期でreject()されるClient Action呼び出しをし、適切なエラー処理コールバックを提供しない場合

3.2と同じ方法で別のClient Actionを読んでいるが、こちらでは、呼び出したClient Action内のJavaScriptが\$reject()呼び出しで終わっている。
\$reject()は、非同期のJavaScriptが失敗で終わったことを示す呼び出し。本来であれば、then関数の第2引数に設定するコールバック関数か、thenにつなげるcatch関数に設定するコールバック関数で処理する。この例では、あえてどちらも設定せず、どうなるか確認している。

$actions.AsynchronousClientActionWithReject().then(function(result) {
  $parameters.Out1 = result;
  $resolve();
} );

AsynchronousClientActionWithReject Action内のJavaScript
$parameters.Out1 = "Rejected";
$reject();

結果としては、ローコード部分のException Handlerには引っかからなかった。

3.4 非同期でreject()されるClient Action呼び出しをし、thenの第2引数で例外を発生させる

今度は、thenの第2引数(onRejectedコールバック関数)を提供し、その中で例外を発生させている。

$actions.AsynchronousClientActionWithReject().then(function(result) {
  $parameters.Out1 = result;
  $resolve();
}, function (error) {
    throw("rethrow from the second callback of then: " + error);
});

同じく、ローコード部分のException Handlerには引っかからなかった。

3.5 非同期でreject()の代わりに例外throwで終わるClient Action呼び出しをし、thenの第2引数で例外を発生させる

$actions.AsynchronousClientActionWithException().then(function(result) {
  $parameters.Out1 = result;
  $resolve();
}, function (error) {
    throw("rethrow from the second callback of then: " + error);
});

AsynchronousClientActionWithException Action内のJavaScript
$parameters.Out1 = "正常終了";
throw("throw an exception from inside of asynchronous JavaScript in a Client Action: test");
$resolve();

このパターンも、ローコード部分のException Handlerには引っかからなかった。

確認結果から

以上の結果から、「非同期JavaScriptを呼ぶときは、thenの第2引数(onRejectedコールバック)かcatchを設定する」ことが必要(ローコード部分のException Handlerでは処理できないため)。

ドキュメント(Call an Asynchronous Client Action)に記載されていた以下の記述とも符合する。

You should always include error handling code when calling asynchronous client actions in JavaScript using one of the two approaches presented above: "then(onFullfilled, onRejected)" or "catch(onRejected)".

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