【GAS】GoogleClassroomの取得上限以上のリストを取り出す方法(nextPageToken)

こんにちは！GoogleAppsScriptを使った業務効率化に夢中の初心者プログラマー、太郎です。

今日は**GoogleClassroomの取得上限以上のリストを取り出す方法**について書いていきたいと思います。

初心者向けですが、javascriptの基本的なルールは押さえておいた方が理解はしやすいと思いますので、まだの方は[Progate](https://prog-8.com/dashboard)でサクッとjavascriptの文法を学習してみてください。

また、`ReferenceError: Classroom is not defined`とエラーが出てしまった方は、[こちらの記事](https://qiita.com/coticoticotty/items/fd73cf477140349b2809)を参考にしてみてください。
では、早速トライしていきましょう！
##GoogleClassroomで一度に取得できるリスト上限は30
前回の記事で、[Classroomに所属している生徒の一覧を取得する方法](https://qiita.com/coticoticotty/items/6d424482182a557a8600)について書いたのですが、どうもこのやり方だと、Classroomでは30人分までしかデータを取得できないことが分かりました。

```javascript
let studentList = Classroom.Courses.Students.list(courseId);
```
所属が30以上いるクラスの場合は、違うやり方をしないといけなさそうですね。ちなみに、確認はしていないのですが、教師のリストや配布した課題のリストを取得する際にもこの上限が適応されるみたいです。
[公式ドキュメント](https://developers.google.com/classroom/reference/rest/v1/courses.students/list#body.ListStudentsResponse.FIELDS.next_page_token)を見てみるとリストを呼び出す際の上限が設定できそうな`pageSize`というパラメーターを発見！おっ、これは行けるかもと、こんな風に書き換えて実行してみると、、、

```javascript
let studentList = Classroom.Courses.Students.list(courseId, {"pageSize": 1000);
```
はい、これでもダメでしたね。よくよく読むと
`The server may return fewer than the specified number of results.`
⇒**サーバーは指定された値よりも小さい値を返すかも(ﾃﾍﾍﾟﾛ)**
と書いてありますね。（いやっﾃﾍﾍﾟﾛは書いてない。。。）

**「いや、『かも』って何だよ！というかﾃﾍﾍﾟﾛすんな！！！」**と初心者にはまったく優しくない公式ドキュメント様に不満をぶつけつつ（いやっ、、、だからﾃﾍﾍﾟﾛは書いてない。。。）、他の方法を探してみると、どうも`pageToken`というパラメーターが鍵になっているようです。
##pageTokenとは？
`pageToken`とは、簡単に言えば本のしおりみたいなもの。「ここからデータを取得するよ～～～」と教えてくれるパラメーターです。
デフォルトではnullに設定されています。

```javascript
let studentList = Classroom.Courses.Students.list(courseId);
Logger.log(students.pageToken);//「null」が出力される
```
ただ、空の値を代入して設定するのが通常みたいですね。こんな風に書いてある例が多いです。

```javascript
let pageToken = "";
let studentList = Classroom.Courses.Students.list(courseId, {"pageToken": pageToken);
```
なんとなく仕組みが分かった気がするのでこんな風に書いてみると、、、

```javascript
let pageToken = "";
let firstStudentList = Classroom.Courses.Students.list(courseId, {"pageToken": pageToken);
let secondStudentList = Classroom.Courses.Students.list(courseId, {"pageToken": pageToken);
```
はい、`firstStudentList`と`secondStudentList`には全く同じ情報が格納されます、笑。どちらも0ページ目から30ページ目の情報が入ってしまうんですね。
##nextPageTokenでしおりを『挟む』
実は、`pageToken`は**本のしおりの位置を教えてくれるだけ**で、しおりを挟んでくれるわけではないんですね。しおりを挟むために重要なのが、「ここまで読んだ！」という情報を教えてくれる、`nextPageToken`というパラメーターです。

この`nextPageToken`は、一度リスト取得を実行すると、自動で設定されます。

```javascript
let pageToken = "";
let firstStudentList = Classroom.Courses.Students.list(courseId, {"pageToken": pageToken);
Logger.log(firststudentList.nextPageToken);//「なんか長い文字列」が出力されるはずです。
```
この**『ここまで読んだよ』情報＝`nextPageToken`**を**『この位置から読み始めるよ情報』=`pageToken`**の値に設定してあげれば、ようやくしおりが挟めます。

```javascript
let pageToken = "";
let firstStudentList = Classroom.Courses.Students.list(courseId, {"pageToken": pageToken);
pageToken = firstStudentList.nextPageToken;//しおりを挟む！
```
こうですね！
この`pageToken`を次の呼び出し時に使えば、前回の続きからデータを取得できます。

```javascript
let pageToken = "";
let firstStudentList = Classroom.Courses.Students.list(courseId, {"pageToken": pageToken);
pageToken = firstStudentList.nextPageToken;//しおりを挟む！（1回目）
let secondStudentList = Classroom.Courses.Students.list(courseId, {"pageToken": pageToken);
pageToken = secondStudentList.nextPageToken;//しおりを挟む！（2回目）
let thirdStudentList = Classroom.Courses.Students.list(courseId, {"pageToken": pageToken);
pageToken = thirdStudentList.nextPageToken;//しおりを挟む！（3回目）
//・・・以下繰り返し
```
このように`pageToken`と`nextPageToken`を使えば、Classroomの上限数30を超えてリストを取得できます。
もちろん、上の記述ではダサいので、繰り返しの処理してあげる必要があります。
##do{} whileを使う
いろいろ調べてみたのですが、今のところ`do {} while`のメソッドを使った書き方が一番しっくり来たのでそちらを紹介します。なお、リストから生徒のメールアドレス一覧を取得して、それを配列として格納していきます。メールアドレスの取得方法の詳しいやり方は[Classroomに所属している生徒の一覧を取得する方法](https://qiita.com/coticoticotty/items/6d424482182a557a8600)を参考にしてください。

```javascript
let pageToken = "";
do {
  let studentList = Classroom.Courses.Students.list(courseId, {"pageToken": pageToken);
  let studentEmailList = [];// 空の配列を用意
  for (i = 0; i < studentList['students'].length; i++){
    let student = studentList['students'][i];
    studentEmailList.push(student['profile']['emailAddress']);//生徒のアドレスを配列に追加
  }
  pageToken = studentList.nextPageToken;//しおりを挟む。最後のページでなければまた「do」する
} while (pageToken);//最後のページまで行ったら処理を辞める
```
`do{} while()`メソッドは、whileがFalse(今回はpageToken=null)にならない限り、doを続けるというメソッドです。
`nextPageToken`は次のデータがない（最後のページまで読み終えたら）、`null`を返してくれるので、そうなったら処理を辞めてくれるんですね。
これで、上限30を超えてリストが取得できます！

以上、参考になれば嬉しいです。いや～～～しかし、今回も分からな過ぎて、pageTokenに関してのいろんな記事を読んだのですが、、、
なんでこうも初心者に分かりづらい、ないし、けっこう間違っている記事が多いのでしょうか。。。この辺の不親切さが、プログラミング学習に挫折する要因になっているような気がします。
Google Classroom APIは日本語の情報が少ないため、今後も様々トライしてみた結果を記事に書いていきたいと思います！