イベントハンドラー登録の適切なタイミングについて

目次

はじめに

kintoneの画面表示時に発生するイベントハンドラーの登録タイミングが遅いと、そのイベントの発生を受け取れないことがあります。

この記事では、次の内容を解説します。

  • kintoneの画面表示イベントが発生するタイミング
  • イベントハンドラーの登録が遅い時の警告表示
  • 適切なタイミングでイベントハンドラーを登録する書き方

kintoneの画面表示イベントが発生するタイミング

ブラウザーがkintoneのページを読み込む時、kintone本体のJavaScriptや、カスタマイズによるJavaScriptは次の順番で実行されます。

  1. ブラウザーがページのHTML読み込みを開始する。
  2. kintoneのJavaScript APIを使うための初期化が行われる。
  3. カスタマイズJavaScriptとして登録されたスクリプトが読み込まれる。
  4. kintone本体のJavaScriptによるページ初期化処理が開始される。
  5. ブラウザーがページのHTMLを読み終わり、DOMContentLoadedイベントを発生させる。
    参考(外部サイト): Document: DOMContentLoadedイベント (External link)
  6. HTMLで指定されている画像などのリソース読み込みが完了した後、ブラウザーはloadイベントを発生させる。
    参考(外部サイト): Window: loadイベント (External link)

jQueryを使った場合など、慣例的なJavaScriptの書き方の一部には、5. のDOMContentLoadedイベントや6. のloadイベントのイベントハンドラーで処理を始めるものがあります。

kintoneでは、これらのイベントよりも早い4. のタイミングで、kintone本体の処理を始める方法を採用しています。
したがって、kintoneの画面表示イベントが、DOMContentLoadedイベントより先に発生することがあります。

tips
補足

kintoneは画面上に表示する多くのコンポーネントをJavaScriptにより描画しています。
そのため、ブラウザーが発生させるDOMContentLoadedやloadイベントの完了と、kintoneのDOM構築が完了するタイミングには直接的な前後関係はありません。

イベントハンドラーの登録よりもイベントが先に発生した場合、イベントハンドラーは呼び出されません。
そのため、DOMContentLoadedやloadイベント内で、kintoneにイベントハンドラーを登録している場合、イベントハンドラーを呼び出しできないことがあります。

具体的には、次のイベントが該当します。

  • app.record.create.show
  • app.record.edit.show
  • app.record.detail.show

これらの画面表示時のイベントを確実にハンドリングするには、3. のカスタマイズJavaScriptが読み込まれた時に、同期的にkintone.events.on()によりイベントハンドラーを登録してください。

警告の表示

kintone.events.on()によるイベントハンドラーの登録が、3. のカスタマイズJavaScriptが読み込まれた時に同期的に実行されていない場合、次のような警告がブラウザーの開発者コンソールに表示されることがあります。

app.record.create.show、app.record.edit.show、app.record.detail.showの登録がない場合、または、カスタマイズ読み込み時に適切なタイミングで登録されている場合は表示されません。
この警告が表示された場合は、以降の書き方の例を参考に、イベントハンドラーの登録タイミングの修正をお願いします。

書き方の例

jQueryを使った書き方

良くない例

jQueryを使った慣例的な書き方のひとつに、JavaScriptでの処理全体を$(() => {...});で囲んで書くというものがあります。

1
2
3
4
5
$(() => {
  kintone.events.on('app.record.create.show', (event) => {
    window.alert('レコード追加イベントが呼び出されました');
  });
});

jQueryの仕様では、この書き方はDOMContentLoadedイベントのイベントハンドラー内で{...}部分を実行することに相当します。

1
2
3
4
5
document.addEventListener('DOMContentLoaded', (loadedEvent) => {
  kintone.events.on('app.record.create.show', (event) => {
    window.alert('レコード追加イベントが呼び出されました');
  });
});

前述のとおり、DOMContentLoadedイベントは、kintone本体のJavaScriptによるページ初期化処理よりも後に実行されます。
そのため、この書き方ではapp.record.create.showイベントの発生よりも、kintone.events.on()によるイベントハンドラーの登録が後になってしまい、イベントハンドラーを呼び出しできないことがあります。

良い例

少し複雑になりますが、jQueryのグローバル変数を捕捉する書き方と組み合わせると、次のようになります。

1
2
3
4
5
6
7
(($) => {
  'use strict';

  kintone.events.on('app.record.create.show', (event) => {
    window.alert('レコード追加イベントが呼び出されました');
  });
})(jQuery);

なお、カスタマイズの処理内容によっては、DOMContentLoadedイベントを待ってから処理を始める必要があるかもしれません。
その場合は、kintone.events.on()によるイベントハンドラーの登録と、$(() => {...});による処理を分けて書いてください。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
(($) => {
  'use strict';

  kintone.events.on('app.record.create.show', (event) => {
    window.alert('レコード追加イベントが呼び出されました');
  });

  $(() => {
    // DOMContentLoadedを待つ必要がある処理はこちらに書く
    // ...
  });
})(jQuery);

一般的な例

jQueryを使わない場合も、app.record.create.showなどのイベントハンドラーの登録は、カスタマイズのスクリプトが読み込まれた時に、同期実行されるように実装してください。

良くない例

DOMContentLoadedのイベントハンドラー内で、app.record.create.showなどのイベントハンドラーを登録している例です。

1
2
3
4
5
6
7
8
9
(() => {
  'use strict';

  document.addEventListener('DOMContentLoaded', (loadedEvent) => {
    kintone.events.on('app.record.create.show', (event) => {
      window.alert('レコード追加イベントが呼び出されました');
    });
  });
})();

loadのイベントハンドラー内で、app.record.create.showなどのイベントハンドラーを登録している例です。
loadイベントは、DOMContentLoadedより、さらにあとに呼び出されるため、loadイベントハンドラーでの登録も避けてください。

1
2
3
4
5
6
7
8
9
(() => {
  'use strict';

  window.addEventListener('load', (loadedEvent) => {
    kintone.events.on('app.record.create.show', (event) => {
      window.alert('レコード追加イベントが呼び出されました');
    });
  });
})();

その他、非同期リクエストのコールバックなど、非同期処理のコールバックで非同期に登録している例です。

1
2
3
4
5
6
7
8
9
(() => {
  'use strict';

  kintone.api(kintone.api.url('/k/v1/records', true), 'GET', {app: 1}, (result) => {
    kintone.events.on('app.record.create.show', (event) => {
      window.alert('レコード追加イベントが呼び出されました');
    });
  });
})();
良い例
1
2
3
4
5
6
7
(() => {
  'use strict';

  kintone.events.on('app.record.create.show', (event) => {
    window.alert('レコード追加イベントが呼び出されました');
  });
})();

まとめ

画面表示時にkintoneが発生させるイベントのタイミングと、それらのイベントを受け取るイベントハンドラーの適切な登録方法を紹介しました。

イベントハンドラーの登録タイミングを適切に設定していないことで警告が表示されている場合も、一見問題なく動作する場合はあります。
しかし、ネットワークの遅延やクライアントPCの性能、他のカスタマイズスクリプトの影響などにより、非同期処理でのイベントハンドラーの登録が大きく遅延し、トラブルの原因となることがあります。
今回紹介した例を参考に、適切なタイミングでのイベントハンドラーの登録にご留意いただければ幸いです。

information

このTipsは、2018年7月版kintoneで動作を確認しています。