繰り返しメールアドレスの重複チェックをして、アカウント名を変更していきながら重複なしでPUTしたい

背景・実現したいこと

毎回初心者な質問で申し訳ございません。
こちらの情報やいろいろ投稿を確認しているのですが、
どのように形にしてよいのかわからなかったため投稿いたします。

実現したいことは、
アカウント作成ボタンをクリックしたら、メールアドレスを生成して、
ローマ字変換したメールアドレスを登録したい。
その際に、同姓同名で重複した場合には、数字を附番してエラーなく登録したいと考えております。
(例)taro.yamada@test.comが重複したら、taro.yamada2@test.com
taro.yamada2@test.comが重複したら、taro.yamada3@test.com
という感じで、@以下を重複が確認できたタイミングでナンバリングしていく。

 

エラー情報 (開発者ツールのコンソール)

ただ、 下記コードではエラーになるどころか、そもそも最初のwhile文の中で最初にGETしたタイミングで終わってしまいます。
returnしているので当然かとは思いますが、returnをとるとエラーにもならずに処理が通過してしまいます。
thenを使うことになるのかとも考えたのですが、よくわからずごちゃごちゃになってしまったため、これ以上どうしたらよいかわからない状況です。

利用したソースコード

(() => {
  'use strict';
kintone.events.on('app.record.detail.show', (event) => {
    var APP_ID;
    var body;
  var flg=0;
    
    // メニューの上側の空白部分にボタンを設置
    const myIndexButton1 = document.createElement('button');
    myIndexButton1.id = 'my_index_button1';
    myIndexButton1.innerText = 'GWSアカウント作成';
    myIndexButton1.onclick = () => {
 
/* クリックイベント */
  APP_ID = 165; /* アプリの番号 */
  var mail = '';
  var sei = 'yamada';
  var mei = 'taro';
  var account = mei + "." + sei;
  var cnt = 1;
  var flg = 0;
      
  while(flg === 0){
    // 重複があった場合には@前に数字をカウントアップ
if(cnt===1){
      mail = mei + "." + sei + "@test.com";
    }else{
      mail = mei + "." + sei + cnt + "@test.com";
    }
        
    body = {
      app: 165,
      query: 'mail= "' + mail + '"'
    };
        
   // アプリ内に同じメールアドレスがないかGETで確認
    return kintone.api(kintone.api.url('/k/v1/record.json', true), 'GET', body)
        .then((res) => {
      // success
      console.log(resp);
       cnt += 1;
    }, (error) => {
      // error
      console.log(error);
    flg=1;
    });
  }
      
  // mailフィールドの値を更新する
  return kintone.api(
    kintone.api.url("/k/v1/record.json", true), "PUT", body, (resp) => {
      // 更新できたらリロード
      location.reload();
    }, (error) => {
      console.log(error);
    }
  );
};
// ボタンを配置するスペース
var el = kintone.app.record.getHeaderMenuSpaceElement();
  
// スペースに作成したボタンを追加
el.appendChild(myIndexButton1);

  });
})();

 

繰り返し処理の考え方がそもそも間違っているのかと思いますが、数日あれこれ試しても全く進展しないため、ご教示いただけますと幸いです。

FUJI さん

ループ内で毎回APIリクエストするのはパフォーマンスが悪いので、メールアドレス重複検知は下記の方法を検討してみてはいかがでしょうか。

  1. メールアドレスのアカウント部分を部分一致レコード一括取得

    メールアドレス like “taro.yamada”

  2. 取得したメールアドレスの中に重複対象があればナンバリング部分を取得し最大値を取得

    let number;

    for (const record of records) {
    const matches = record.メールアドレス.value.match(/^taro.yamada(\d+)?@/);
    if (matches) {
    number = Math.max(number, matches[1]);
    }
    }

    if (number) {
    // 更新処理
    }

 

 

ちなみに、ループ処理で1件ずつ Promise の処理する場合は async await を使用をお勧めします。(ブラウザのバージョン要件にもよりますが、よほど古いものでなければ動きます)

kintone.events.on("app.record...", async (event) => {
for (...) {
   // データを取得するまで次のループに行かず待機します
 const result = await kintone.api(...);
}
return event;
});

 

以上になります。何か不明な点がありましたら、気兼ねなくご質問ください。

901324675146さま
この度は細かくアドバイスいただきありがとうございます。

まだjsのことや正規表現を理解しきれていないため、
とんちんかんなご質問になってしまっていたら申し訳ございません。

確認したことで2点不明点があったため、ご質問させていただきます。

 

  1. メールアドレスのアカウント部分を部分一致レコード一括取得

こちらについては、実際の処理では姓と名は変数(account)のため、
queryは下記のように設定してみました。

account = mei + '.' + sei;

 body = {
      app: 165,
      query: 'メールアドレス like "' +  account + '"'
  };

しかし、たとえば下記2つのアドレスが登録されていても、
GETで取得できたのはナンバリングのついていないほうだけでした。
taro.yamada@sample.com
taro.yamada2@sample.com

どの箇所を修正すればよろしいでしょうか?

  1. 取得したメールアドレスの中に重複対象があればナンバリング部分を取得し最大値を取得

次は、ナンバリング部分の取得についてですが、
ご教示いただいたコードでは、取得できるナンバリングは1~9までかと思います。

const matches = record.メールアドレス.value.match(/^taro\.yamada(\d+)?@/);

こちらを2以上(10を超える場合を想定して)の場合には、どのように設定すればよろしいでしょうか?
アカウント(例でいうtaro.yamada)が変数なので、どのように正規表現を書いたらいいかわからずにいます。

調べた限りでは、変数の場合にはRegExpを使うと書いてあったのが、今回の場合にはどのようにすればよいかご教示いただけますと幸いです。
https://www.sejuku.net/blog/24896

FUJI さん

メールアドレスの件ですが、kintone の仕様で検索に引っかからないパターンになっていました。昔これを回避する検索プラグインを作ったこともありますが、失念しておりました。申し訳ありません。

回避策として、taro.yamada.2 のように番号の前に英数以外の文字「.」等を入れることで上記の検索の仕様は回避できますが、運用上可能でしょうか?

運用の仕様変更が難しい場合は少しヒット件数が増えますが、taro で検索すると「taro.yamada」「taro.yamada2」は取得できます。逆に taromaru のような文字列はヒットしません。

また、正規表現に関してはJavaScriptガイドを参考に下記のような処理で解決できると思います。

const account = "taro.yamada";
const pattern = new RegExp("^" + escapeRegExp(account) + "(\\d+)?@");
const matches = "taro.yamada123@example.com".match(pattern);

console.log(matches[1]); // 123 が出力

function escapeRegExp(string) {
  return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}

以上になります。参考になれば幸いです。

901324675146さま

ご返信が遅くなり申し訳ございません。

回避策として、taro.yamada.2 のように番号の前に英数以外の文字「.」等を入れることで上記の検索の仕様は回避できますが、運用上可能でしょうか?

こちらについては、運用上難しいようだったので、アドバイスいただいたように名前で検索して絞り込む方法でなんとか想定通りに動作できるようになりました!

いろいろアドバイスいただき、誠にありがとうございました。