【ServiceNow】初心者向け next()とhasNext()

こんにちは。ServiceNow担当のT Aです
ServiceNowで提供されるAPIには様々な種類がありますが、中には似たような名前で使い方を混同してしまうものもあります。
今回は、その1つとしてnext()とhasNext()を紹介します。
本記事では、「next()とhasNext()の違いは何?どう使い分けたらいいの?」
そんな疑問にお答えするためにそれぞれの違いや使い方についてわかりやすく解説していければと思います。
コード紹介
今回のコードの概要はこんな感じ
var grRec = new GlideRecord("incident");
grRec.addQuery("short_description", "next hasnext");
grRec.query();
//↓をnextにした場合とhasNextにした場合を考える。
while (grRec.〇〇()) {
var numData = grRec.getValue("number");
gs.info(numData);
}
3行目でクエリをした結果、2つのレコードがヒットした場合を考えてみましょう。
next()の場合
まずはnext()の場合を見てみます。
※無限ループに陥る可能性がありますので、先ほどのコードをそのまま使用するのではなく、最大10回ループしたら終了するように手を加えております。
var grRec = new GlideRecord("incident");
grRec.addQuery("short_description", "next hasnext");
grRec.query();
var count = 0;
//↓をnextとする。
while (grRec.next()) {
count = count + 1;
var numData = grRec.getValue("number");
gs.info("ループ回数は " + count);
gs.info("インシデント番号は " + numData);
if (count == 10) {
break;
}
}
この場合、ログにはどのように出てくるでしょうか。
結果としては以下の画像のようになります。
hasNext()の場合
では、hasNext()の場合はどうなるでしょうか。
var grRec = new GlideRecord("incident");
grRec.addQuery("short_description", "next hasnext");
grRec.query();
var count = 0;
//↓をhasNextとする。
while (grRec.hasNext()) {
count = count + 1;
var numData = grRec.getValue("number");
gs.info("ループ回数は " + count);
gs.info("インシデント番号は " + numData);
if (count == 10) {
break;
}
}
出てくるログとしてはこちらです。
恐ろしいですね。。なんとnext()をhasNext()に変更しただけで無限ループになってしまいました。
※例としてお出ししているスクリプトは無限ループを防ぐために10回ループしたら強制終了するようにプログラムしていますのでご安心ください。
しかも、取得したかったインシデント番号が取得できていないです。
原因は何でしょうか?
next()とhasNext()の違い
結論からいうと、next()とhasNext()ではポインタ(どのレコードにフォーカスしているか)が異なります。
まずは next()のポインタの動きから確認しましょう。
このように、処理に応じてポインタが動いていきます。
レコード自体にポインタが付いて回るので、そのレコードの情報を取得・更新できるわけです。
続いて、hasNext()のポインタの動きを見ていきましょう。
あれ?ポインタが動いていない…??
そうなんです。hasNext()は「次のレコードが存在するか」を確認するためのものであり、ポインタを動かしません。
つまり、上図だとINC00001のレコードが存在するかをずーーっと確認し続ける処理となっております。
また、存在を確認するだけでレコード自体にポインタが当たっていないのでデータの取得・更新できません。
だから先ほどの例では無限ループ+インシデント番号が取得できていなかったんですね。
next()とhasNext()の使い分け
どのように使い分ければよいのか例をご紹介します。
next()はレコードのデータの取得・更新を行いたいときに使用します。
もしくは、クエリの結果が複数であり、クエリ結果の数が重要であれば使うと良いでしょう。
hasNext()はレコードが存在するかどうかを確認したい場合に使います。
したがって、使用用途として多いのはwhile (grRec.hasNext()) ではなくif (grRec.hasNext()) となりますので、使い方に注意しましょう。
もう少し言及すると、hasNext()のほうが軽い処理となります。
もちろん単体では見てわかるようなパフォーマンスの差にはなりませんが、たくさんの積み重ねの中でだんだんと蓄積されていきます。
「データの中身自体には問題がなく、レコードが存在しているか」のみを確認したい場合にはhasNext()を使用するのが無難です。
まとめ
今回の記事は少し細かい部分となりましたが、ご納得いただけましたでしょうか。
「どうしてもwhileの中でhasNextを使いたいんだ!」「次のレコードがないとnext()したくない!」という方は
while (grRec.hasNext()) { //次のレコードがあるかを確認して
grRec.next(); //存在するならばポインタを動かしてから
var setumei = grRec.short_description; //データの取得などを行う。
}
上記のようにすると無限ループに陥らないと思います。(使用用途はかなり限られそうですが…)
皆様の学習の助けになれば幸いです。
参考:Docs解説ページ
参考:Developer向けAPIs
ServiceNowを活用した業務改善をするなら、システムサポートのServiceNow導入サービスをよろしくお願いします。