Promiseでレコード取得した際に時々エラーが出る

kintone API で Promise を使ってみよう!

を参考にレコード保存時にPromiseで別レコード取得して色々と処理をするコードを書きました。

そのコードを実行すると成功したり、失敗したりと挙動が不安定です。

成功・失敗時に条件は何も変えておりません。ただ保存ボタンを押しただけです。

原因調査のため下記の単純なコードに変更して実行したところ、

同じように成功したり失敗したりします。

 (function() {
    “use strict”;

    var AppId = 11; //アプリID
    var queryAll = ‘’; //クエリの条件指定なし

    /*詳細画面表示イベントハンドラ*/
    kintone.events.on([‘app.record.create.submit.success’], function(event) {

        getRecords(AppId, queryAll).then(RSuccess).catch(apiRequestError);
        getRecords(AppId, queryAll).then(RSuccess).catch(apiRequestError);
        getRecords(AppId, queryAll).then(RSuccess).catch(apiRequestError);
        getRecords(AppId, queryAll).then(RSuccess).catch(apiRequestError);
        getRecords(AppId, queryAll).then(RSuccess).catch(apiRequestError);
        getRecords(AppId, queryAll).then(RSuccess).catch(apiRequestError);
        getRecords(AppId, queryAll).then(RSuccess).catch(apiRequestError);
        getRecords(AppId, queryAll).then(RSuccess).catch(apiRequestError);
        
        
    });
    
    var RSuccess = function(rLog) {
        console.log(‘RSuccess’);
        console.log(rLog);
    };

    var apiRequestError = function(error) {
        /* API失敗時の処理 */
        console.log(‘API失敗’);
        console.log(error);
        //エラーメッセージ表示
        alert('エラーが発生しました ’ + error);
    };

    //500件ずつ取得処理
    function getRecords(appId, optQuery, optRecords, optOffset) {
        var offset = optOffset || 0;
        var limit = 500;
        var allRecords = optRecords || [];
        var reqParam = {
            app: appId,
            query: optQuery + ’ limit ’ + limit + ’ offset ’ + offset
        };
        console.log(reqParam);
        return kintone.api(‘/k/v1/records’, ‘GET’, reqParam).then(function(resp) {
            allRecords = allRecords.concat(resp.records);
            if (resp.records.length === limit) {
                return getRecords(appId, optQuery, allRecords, offset + limit);
            }
            return allRecords;
        });
    }

})();

promiseのレコード取得を何度も呼び出すコードです。

全部成功する場合と、4番目の呼び出しで失敗する場合があります。

console.log(error);でエラー内容を確認しようと思ったのですが、何も出力されません。

同じような現象に遭遇した方はいらっしゃいますでしょうか。

コードの記載方法で何か問題があるようであればご指摘いただきたいです。

ponkichi31さん
cstapの瀧ヶ平です。

記載されているコードを見る限り、コード自体に問題はなさそうに感じます。
(totalCount:true にして、allRecordsが総件数に満たない場合に再帰するようにした方がレコードが少ないアプリにも対応できるので良いかとは思いますが)

エラーは発生した段階での(alertが表示されているときの)コンソールの出力、
また、エラーが発生したタイミングのリクエストの詳細などはわかりますでしょうか?
お教えいただけると幸いです。

コード自体は問題なさそうなので、REST APIのエラーかkintone側のエラーなのかなあと推測できますが…

瀧ヶ平様

コメントありがとうございます。

errorの中身は何も出力されませんでした・・・。

アラートは表示されているのですが。

詳細は確認してみます。

 

 

ponkichi31さん

getRecords の呼出しを順番に並べていますが、処理的にはパラレルで実行されます。
そのため、何らかのリソース競合かAPI同時呼出し制限が発生している可能性があります。
getRecordsを順番に処理させたい場合は、thenのメソッドチェーンで呼び出します。
return event などの処理も追加したほうがいいと思いますので、記述方法は他のPromise処理を参考にしてください。

rex0220様

コメントありがとうございます。こちら本来のコードはthenのメソッドチェーンで呼び出していたのですが、簡略化のつもりでこのように記載してみました。結果としてAPI同時呼び出し制限のリスクがあるとのことでご指摘ありがとうございました。

レコード呼び出しをthenのメソッドチェーンで実施してみました。他の部分は変更しておりません。

     /*詳細画面表示イベントハンドラ*/
     kintone.events.on([‘app.record.create.submit.success’], function(event) {

         getRecords(AppId, queryAll).then(function(result) {
             console.log(‘成功1’ + result);
             getRecords(AppId, queryAll).then(function(result) {
                 console.log(‘成功2’ + result);
                 getRecords(AppId, queryAll).then(function(result) {
                     console.log(‘成功3’ + result);
                     getRecords(AppId, queryAll).then(function(result) {
                         console.log(‘成功4’ + result);
                         getRecords(AppId, queryAll).then(function(result) {
                             console.log(‘成功5’ + result);
                         }).catch(function(error) {
                             console.log(‘失敗5’ + error);
                         });
                     }).catch(function(error) {
                         console.log(‘失敗4’ + error);
                     });
                 }).catch(function(error) {
                     console.log(‘失敗3’ + error);
                 });
             }).catch(function(error) {
                 console.log(‘失敗2’ + error);
             });
         }).catch(function(error) {
             console.log(‘失敗1’ + error);
         });
         
         return event;

     });

これを何度か実行すると、失敗2、失敗3、失敗4のいずれかが表示されます。errorは空文字です。

記載方法に問題がありましたらご指摘いただけると幸いです。

ponkichi31さん

今のreturn event の位置だとgetRecords処理終了前に、イベント処理が終わってしまう気がします。
return eventは、処理終了時に行います。
ただし、エラーの原因は別にあるような気がします。
とりあえず下記コードで順番に実行されると思いますのでエラー個所を特定するためステップ実行で試してください。

 console.log('成功1' + result);  
 getRecords(AppId, queryAll).then(function(result) {  
 console.log('成功2' + result);  
 getRecords(AppId, queryAll).then(function(result) {  
 console.log('成功3' + result);  
 getRecords(AppId, queryAll).then(function(result) {  
 console.log('成功4' + result);  
 getRecords(AppId, queryAll).then(function(result) {  
 console.log('成功5' + result);  
 return event;  
 }).catch(function(error) {  
 console.log('失敗5' + error);  
 return event;  
 });  
 }).catch(function(error) {  
 console.log('失敗4' + error);  
 return event;  
 });  
 }).catch(function(error) {  
 console.log('失敗3' + error);  
 return event;  
 });  
 }).catch(function(error) {  
 console.log('失敗2' + error);  
 return event;  
 });  
 }).catch(function(error) {  
 console.log('失敗1' + error);  
 return event;  
 });  

ponkichi31さん

こちらでも検証してみました。どうも app.record.create.submit.success の問題の可能性があります。

chrome で実行した場合、発生したエラーは、APIで「Provisional headers are shown」となりました。

chrome ネットワークの履歴を見ると、api 処理中にもかかわらず、「show」 処理がコールされています。
たぶん、これにより画面が切り替わり、api が「Provisional headers are shown」になっている可能性があります。

 

IEで実行してみると、エラーは発生しないのですが、APIの処理が途中で終わっているようです。
たぶん、「show」により画面遷移してしまって処理できなくなったと思われます。

試しに、change イベント処理で同じロジックを実行すると最後まで問題なく実行されます。

ponkichi31さんでも同様の現象になりますか?

本対策としては、return event されるまで「show」処理がされないように、kintone 側の対策を待つしかないです。

暫定対応としては、別のイベント処理で該当ロジックを処理します。
submit.successイベントでセッションストレージを使って処理リクエストを渡し、
show イベント時にセッションストレージを見てリクエストがあれば処理し、セッションストレージをクリアします。
これは、以前はsubmit.success が無かったため、submit更新後処理として私が行っていた方法です。

他にも対応方法があれば、コメントをお願いします。

 

rex0220様

色々とお調べいただきましてありがとうございました。

改めてAPIを調べてみたところ、submit.successはまだサポートされているのか不明でした。そこで7月時点でサポートされたと書いてあったsubmitにイベントを変えて実施したところ、同様のエラーが出ました。ネットワーク情報を確認したところ、エラーとなったところでご提示いただいたshowのコールを確認できました。showとchangeのイベントで同じコードを実施したところエラーは出ませんでした。

ご提示いただいた回避策以外思いつきませんので、ひとまずsubmit.successイベントで全部処理するのはあきらめて、showイベントにて直前の処理を判別してやりたいことを実施しようと思います。実装できたら改めてコメントさせていただきます。本当にありがとうございました。

ponkichi31さん

すみません。submitイベントでもエラーとなったということで、Promise の呼び出しに問題があることがわかりました。
基本的なことを忘れていました。下記のように変更してください。
これで、submit.success でも return event が呼ばれるまで画面遷移しません。

なお submit.successは8/14から正式サポートされています。

return getRecords(AppId, queryAll).then(function(result) {
console.log(‘成功1’ + result);
return getRecords(AppId, queryAll).then(function(result) {
console.log(‘成功2’ + result);
return getRecords(AppId, queryAll).then(function(result) {
console.log(‘成功3’ + result);
return getRecords(AppId, queryAll).then(function(result) {
console.log(‘成功4’ + result);
return getRecords(AppId, queryAll).then(function(result) {
console.log(‘成功5’ + result);
return event;
}).catch(function(error) {
console.log(‘失敗5’ + error);
return event;
});
}).catch(function(error) {
console.log(‘失敗4’ + error);
return event;
});
}).catch(function(error) {
console.log(‘失敗3’ + error);
return event;
});
}).catch(function(error) {
console.log(‘失敗2’ + error);
return event;
});
}).catch(function(error) {
console.log(‘失敗1’ + error);
return event;
});

 

 

rex0220様

追加の情報ありがとうございました。ご提示いただいたコードを実行したところ、submit.successでもエラーが出ませんでした。結果として私の最初のコードが書き間違っていたということでお恥ずかしい限りです。

Promiseを利用したモダンなアプリの全レコード取得の書き方ではメインの呼び出しではreturnしていませんが、今回教えていただいたようにメインの呼び出しの中でreturnさせると処理終了を待ってくれるという認識でよろしいでしょうか。

ponkichi31さん

kintone API で Promise を使ってみよう!に記述がありますが、
「イベントハンドラでreturnしたPromiseオブジェクトの解決を待つ」というのがポイントです。
結果的に、return event するまで処理終了を待ってくれるようです。

 

rex0220様

丁寧なご回答ありがとうございました。

おかげさまでkintone.promiseの仕組みが多少理解できたと思います。