🌀

kintoneのchangeイベントの無限ループ対策

2023/01/27に公開
1

kintoneのchangeイベント、ループすることがある。

ループしちゃうアプリを作ってみよう

実際にループしてしまうアプリを作ってみることにする。
文字列(1行)フィールドを1つ設置しよう。

フィールドコードはお好みで。(ここでは「文字列」とします。)

ループしちゃうJavaScriptを書く

文字列(1行)フィールドに入力したら末尾に「a」を1つ追加するプログラムを書いた。

(() => {
  'use strict';
  kintone.events.on(['app.record.edit.change.文字列'], (event) => {
    // 文字列の最後に'a'を1こつける
    event.changes.field.value += 'a';
    return event;
  });
})();

ループさせてみよう

新しくレコードを作ってなんでもいいので入力してエンター!
「あ」って入力するとaがたくさん入力されちゃう👀
数値で試したら3000を超えていたのでそのくらいループしちゃう。

なんでループしてるの👀

よくわからないけど、何故かループする👀「2回目」が何故か来ちゃうみたい。
「2回目」のchangeイベントで変化がなければ「確定」って仕様になってるのかな?分からないけど。

↓これはループする。2回目くると増えちゃうからね。

event.changes.field.value += 'a';

↓これだとループしない。2回目きても前の値と変わらないから3回目のchangeイベントには入らないのかも。

event.changes.field.value = 'a';

ちなみに、一覧のchangeイベントでは↓これでもループしない👀

event.changes.field.value += 'a';

無限ループの回避方法

「変更前の値」と「変更後の期待する値」を準備して、changeイベント内で「変更された値」と比較して、「変更された値」と「変更後の期待する値」が一致していたらreturn eventする作戦が良さそう。

日本語難しい。
↓要は、こういうコードを書けばループは回避できる。

(() => {
  'use strict';

  // 変更前の値
  let tmp;  
  
  kintone.events.on(['app.record.edit.show'], (event) => {
    // 最初の値を保存しておく
    tmp = event.record.文字列.value;
    return event;
  });
  
  kintone.events.on(['app.record.edit.change.文字列'], (event) => {
    // 変更された値が変更後の期待する値(今回はtmp + 'a')だったらreturn eventする
    if (event.changes.field.value === tmp +'a'){
      return event;
    }
    // 変更前の値を更新
    tmp = event.changes.field.value;
    // 新しくする
    event.changes.field.value += 'a';
    return event;
  });
})();

まとめ

「前回の値」と「前回の値が変わった値」と「今回の値」という3つの値をジャグリングのように扱って、ループを防いでみました。

これがテーブルのフィールドだったらどうなる?とか
任意のフィールドではどうする?とか
空白はどうしたらいい?みたいな「?」が浮かんでくるかもしれないですが、基本的なやり方は同じ感じでできます。
テーブルは他にも考えないといけないことがあってちょっとめんどいけど。

おしまい。

Discussion

じゅりどんじゅりどん

showの方がeditに、changeのほうがcreateになってるんで、どっちかに揃えてください🙏(あとで修正します)