こんにちは。だいちゃんです。
kintoneに書き込まれたコメントの数をチェックしないといけない用事があり、全レコード総当たりでコメントを取得するAPIを叩いてみたのですが、同期処理/非同期処理の絡みでうまくいかないこととか、めっちゃ処理速度が遅いこととかがあったので、メモ。
ちなみに、レコード数以上にAPIリクエストが飛びます ので、 リクエスト数の上限値超過 にご注意ください。僕はちゃっかり超過のお知らせメールもらいました。
allRecords
にレコードを格納するallRecords
に総当りでコメント取得APIを叩いて、コメント数を取得する ⇐ 今日の本題allRecords
に入れておく)allRecords
を map で処理させて、それを並列で動かすために Promise.all の引数にして、しかもそれが全部終わるまで待ちたいので await つけてる... と思います。
kintone.events.on(['app.record.index.show'], async (e) => {
// allRecords にレコードを格納する処理は省略
// コメント取得にかかる時間を計ります
console.time("commentGet");
// 総当たりでコメント取得API叩いて、コメント数を調べる
await Promise.all(allRecords.map(async(r, index) => {
const firstCommentGetBody = {
"app": e.appId,
"record": allRecords[index]["$id"].value,
"order": "desc"
}
const firstCommentGetResp = await kintone.api('/k/v1/record/comments', 'GET', firstCommentGetBody);
// コメント数(この段階では最大10)
let comment = firstCommentGetResp.comments.length;
// 10件以上コメントがあるかで分岐
if (firstCommentGetResp.older) {
let olderComment = true;
// 古いコメントがある限りループ
for (let i = 1; olderComment; i++) {
const moreCommentGetBody = {
"app": e.appId,
"record": allRecords[index]["$id"].value,
"order": "desc",
"offset": i * 10
}
const moreCommentGetResp = await kintone.api('/k/v1/record/comments', 'GET', moreCommentGetBody);
comment = comment + moreCommentGetResp.comments.length;
olderComment = moreCommentGetResp.older;
}
}
// 最終的なコメント数がわかったら、
// allRecords[i].comment,value に保存
allRecords[index]["comment"] = {
"value": comment
};
}));
console.timeEnd("commentGet");
// 本来なら画面上に表示する処理
console.log(allRecords);
});
commentGet: 17036ms - タイマー終了
For文でぶん回す例です。
直列処理になる分、遅くなってる感じがします。
kintone.events.on(['app.record.index.show'], async (e) => {
// allRecords にレコードを格納する処理は省略
// コメント取得にかかる時間を計ります
console.time("commentGet");
// 総当たりでコメント取得API叩いて、コメント数を調べる
for (let index = 0; index < allRecords.length; index++) {
const firstCommentGetBody = {
"app": e.appId,
"record": allRecords[index]["$id"].value,
"order": "desc"
}
const firstCommentGetResp = await kintone.api('/k/v1/record/comments', 'GET', firstCommentGetBody);
// コメント数(この段階では最大10)
let comment = firstCommentGetResp.comments.length;
// 10件以上コメントがあるかで分岐
if (firstCommentGetResp.older) {
let olderComment = true;
// 古いコメントがある限りループ
for (let i = 1; olderComment; i++) {
const moreCommentGetBody = {
"app": e.appId,
"record": allRecords[index]["$id"].value,
"order": "desc",
"offset": i * 10
}
const moreCommentGetResp = await kintone.api('/k/v1/record/comments', 'GET', moreCommentGetBody);
comment = comment + moreCommentGetResp.comments.length;
olderComment = moreCommentGetResp.older;
}
}
// 最終的なコメント数がわかったら、
// allRecords[i].comment,value に保存
allRecords[index]["comment"] = {
"value": comment
};
};
console.timeEnd("commentGet");
// 本来なら画面上に表示する処理
console.log(allRecords);
});
commentGet: 88077ms - タイマー終了
forEach文の引数で同期関数を指定したとしても、その中では同期処理をするけど、forEach自体は非同期なので、「コメント取得処理(同期)を非同期に呼び出す」現象が起こるみたい。
しかも、呼び出し側が非同期なので、結果を待たずに、全レコード分呼び出しが終わったら取得結果に関わらず、次の画面描画の処理に移っちゃう。よって、コメント数が空のレコードが残ったまま描画が始まって、コケる。
...と思う。
kintone.events.on(['app.record.index.show'], async (e) => {
// allRecords にレコードを格納する処理は省略
// コメント取得にかかる時間を計ります
console.time("commentGet");
// 総当たりでコメント取得API叩いて、コメント数を調べる
allRecords.forEach(async (record, index) => {
const firstCommentGetBody = {
"app": e.appId,
"record": record["$id"].value,
"order": "desc"
}
const firstCommentGetResp = await kintone.api('/k/v1/record/comments', 'GET', firstCommentGetBody);
// コメント数(この段階では最大10)
let comment = firstCommentGetResp.comments.length;
// 10件以上コメントがあるかで分岐
if (firstCommentGetResp.older) {
let olderComment = true;
// 古いコメントがある限りループ
for (let i = 1; olderComment; i++) {
const moreCommentGetBody = {
"app": e.appId,
"record": allRecords[index]["$id"].value,
"order": "desc",
"offset": i * 10
}
const moreCommentGetResp = await kintone.api('/k/v1/record/comments', 'GET', moreCommentGetBody);
comment = comment + moreCommentGetResp.comments.length;
olderComment = moreCommentGetResp.older;
}
}
// 最終的なコメント数がわかったら、
// allRecords[i].comment,value に保存
allRecords[index]["comment"] = {
"value": comment
};
});
console.timeEnd("commentGet");
// 本来なら画面上に表示する処理
console.log(allRecords);
});
commentGet: 3842ms - タイマー終了
最速。ただし、データは取れてない。
ということで、また同期/非同期の話でつっかかったってお話。
「Promiseを返す」とかがまだ今いちピンと来てない。
参考: