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

目次

はじめに

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 で動作を確認しています。