ユーザーの使用状態に応じた処理

【実現したいこと】
あるアプリにユーザー選択フィールドとドロップダウンフィールドがあります。
レコード一覧画面にボタンを設置して、ボタン押下で当該アプリのレコードを全件取得し、
ユーザー選択の値を元に、当該ユーザーの使用状態(valid)を取得して、
validがfalseであればドロップダウンの値を「離職」に更新したいです。
ユーザー選択は1名のみ値が入っています。

【うまくいかない点】
①REST APIでレコード全件取得
②取得したレコード1件ごとにUser APIでユーザーの使用状態を取得してfalseなら「離職」に設定
③REST APIでレコード一括更新
という構成でコードを書きましたが、実行するとコンソールに
net::ERR_INSUFFICIENT_RESOURCES のエラーが発出し、更新されません。

②の処理後にconsole.logで更新対象(records)を確認すると、想定通りの内容になってはいるのですが。。

レコードを全件取得し、その1件ずつに対してUser APIを使用しているためブラウザのメモリ不足のエラーが出ていると推測していますが、この処理を実現するためにどうすれば良いか、お知恵を貸していただきたいです。
よろしくお願いいたします。

//offsetの上限値1万を考慮したレコード一括取得するための関数
    var getRecords = function(_params) {
        var params = _params || {};
        var app = params.app || kintone.app.getId();
        var filterCond = params.filterCond;
        var sortConds = params.sortConds || ['$id asc'];
        var fields = params.fields;
        var data = params.data;
        
        if (!data) {
            data = {
                records: [],
                lastRecordId: 0
            };
        }
        
        var conditions = [];
        var limit = 500;
        if (filterCond) {
            conditions.push(filterCond);
        }
        
        conditions.push('$id > ' + data.lastRecordId);
        
        var sortCondsAndLimit = ' order by ' + sortConds.join(', ') + ' limit ' + limit;
        var query = conditions.join(' and ') + sortCondsAndLimit;
        var body = {
            app: app,
            query: query
        };
        
        if (fields && fields.length > 0) {
          // $id で並び替えを行うため、取得フィールドに「$id」フィールドが含まれていなければ追加します
            if (fields.indexOf('$id') <= -1) {
                fields.push('$id');
            }
            body.fields = fields;
        }
        
        return kintone.api(kintone.api.url('/k/v1/records', true), 'GET', body).then(function(r) {
            data.records = data.records.concat(r.records);
            if (r.records.length === limit) {
                // 取得レコードの件数が limit と同じ場合は、未取得のレコードが残っている場合があるので、getRecords を再帰呼び出して、残りのレコードを取得します
                data.lastRecordId = r.records[r.records.length - 1].$id.value;
                return getRecords({ app:app, filterCond:filterCond, sortConds: sortConds, fields:fields, data:data });
            }
            delete data.lastRecordId;
            return data;
        });
    };
    
    function risyokuHantei(body,recordNum,records){
        kintone.api(kintone.api.url('/v1/users.json', true), 'GET', body).then(function(resp2) {
            if(resp2.users[0].valid === false){
                const record = {
                    "離職": {
                        "value": "離職"
                    }
                };
                records.push({'id': recordNum, 'record': record});
            }
        });
        return records;
    }
    
    
    kintone.events.on("app.record.index.show", function(e) {
        //↓↓区分一括更新処理
        //増殖防止
        if (document.getElementById('my_index_button2') !== null) {
            return;
        }
        
        //ボタン生成        
        var myIndexButton2 = document.createElement('button');
        myIndexButton2.id = 'my_index_button2';
        myIndexButton2.innerText = '離職一括更新';
        
        //ボタンクリック時の処理        
        myIndexButton2.onclick = function() {
            //スピナー表示
            showSpinner();
            
            const app = kintone.app.getId();
            const params = {
                app: app,
                fields: ['$id','ユーザー_ログイン名'] ,
            };
            
            //レコード一括取得の関数を呼び出す
            getRecords(params).then(function(resp) {
                var resprecords = resp.records;
                let records = [];
                
                for (let i = 0; i < resprecords.length; i++) {
                    const resprecord = resprecords[i];
                    const recordNum = resprecord.$id.value;                    
                    let users = [];
                    users.push(resprecord.ユーザー_ログイン名.value[0].code);
                    const body = {
                        codes: users,
                    };
                    risyokuHantei(body,recordNum,records);                    
                }
                //console.log(records);
                    //KintoneRestAPIClientライブラリ使用で、レコード一括更新
                    new KintoneRestAPIClient().record.updateAllRecords({
                        app: kintone.app.getId(),
                        records: records
                    }).then(function(){
                        //更新終了を待ってアラート表示
                        Swal.fire({
                            icon:"success",
                            title: "更新が完了しました。",
                        }).then((result) => {
                            //アラートダイアログのOKボタン押下したら画面リロード
                            location.reload();
                        });
                        //スピナー非表示
                        hideSpinner();
                    });
                
            });
        };       
        kintone.app.getHeaderMenuSpaceElement().appendChild(myIndexButton2).classList.add('btn-square-shadow');
        
        return e;
    });

変更の影響を受けるレコードはどのくらいなのでしょうか?
updateAllRecordsでブラウザのリソース不足ということであれば、
対象データをslice()などで減らして何回かに分ける方法はできませんか?

kintone JavaScript Client(@kintone/rest-api-client)のupdateAllRecordsを使うなら
データ取得の部分も
getAllRecords

を使ったらいいのにと思いました。

「いいね!」 1

コメントありがとうございます。
リソース不足はレコード更新時ではなく、User APIによるユーザー情報取得時に発生していました。
レコード取得の際のgetAllRecordsはその通りですね!
あまり良く考えず、他のアプリなどで似たような処理をしている部分を継ぎ接ぎして書いているのでそこまで気にしていませんでした。ありがとうございます。

自己解決しました。
①レコードを全件取得する。
②レコードのユーザー選択フィールドの値(ユーザー)1件ずつにUser APIを使うのではなく、一旦全レコードのユーザーcodeを配列1に格納する。
③配列1から100件(User APIのsize上限)ずつ抜き出してUser APIでユーザー情報取得し、その取得した情報をさらに別の配列2に格納(push)する。
(User APIにoffsetのパラメータがありますが、そもそも渡すcodesが100件以内でないとエラーが出る。)
④全ユーザー情報を格納完了後、valid=falseのユーザーのみを抽出して配列3に格納する。
⑤①で取得したレコードに対し、ユーザーが配列3に含まれる場合は$idと離職を更新用のrecordsに追加(push)する。
⑥レコード全件更新する。

「いいね!」 1

もし、ユーザーcodeに重複が多いようであれば、処理量を減らすために
Set等を使って重複を省くとよいかもしれません。既にされているかも知れませんが。

「いいね!」 1

重複については気になっていたのですが、とりあえず正常に動いたので放置しておりました。
このような便利なものがあるのですね!
勉強になりました。ありがとうございます。

このトピックはベストアンサーに選ばれた返信から 3 日が経過したので自動的にクローズされました。新たに返信することはできません。