Instagram APIでPaginationを実現する
Instagram APIでユーザフィードはデフォルトで20しか返ってきません。Countパラメータで変更可能ですが、自分が確認したところ、30ぐらいが上限のようです。なのでユーザが見ているときに、"もっと見る"のようなボタンを容易して次を見させるのがよさそうです。
方針は、
- /users/user-id/media/recent に投げる
- レスポンスのデータ処理
- 最後まで読み込んだらボタンを消す
投げるのはサーバ側。max_idはクライアントで持つことがポイントですかね。
1. /users/user-id/media/recent に投げる
/users/self/feedはフォロワーの投稿も入ってしまうので、今回の用途ではこっちは却下。countは30で投げる。処理はサーバ側で。 細かいところは省略するが、以下の感じで投げる。( PerlでMojo::UserAgentを利用) max_idなしで投げると最新の写真から30個ぐらい返ってくる。
sub get_my_feed { my ($self, $access_token, $user_id, $max_id) = @_; my $tx; if (defined $max_id){ $tx = $self->ua->get("https://api.instagram.com/v1/users/$user_id/media/recent?access_token=${access_token}&count=30&max_id=$max_id"); }else { $tx = $self->ua->get("https://api.instagram.com/v1/users/$user_id/media/recent?access_token=${access_token}&count=30"); } return $tx->res->json; }
2. レスポンスのデータ処理
response.pagination.next_max_idに次のmax_idが入ってくるのでこれを次から使う。max_idはクライアント側で持ってて、GETのパラメタでサーバ側に投げる。下記、AngularJSのコード(リファクタリング前で汚いですが、、)
$scope.data = new Array(); $scope.showLoadNext = true; var max_id; $scope.loadNext = function(){ $http({method: 'GET', url: '/api/instagram/feed', params: {max_id: max_id} }). success(function(res, status, headers, config) { if(typeof res.pagination.next_url === "undefined"){ $scope.showLoadNext = false; } $scope.data = $scope.data.concat(res.data); max_id = res.pagination.next_max_id; }). error(function(data, status, headers, config) { // do nothing }); }; $scope.loadNext();
3. 全部表示したらボタンを消す
もっと見続けると最後までいって、next_max_idがundefinedになる。上記のコードのtypeof のラインがそう。AngularJSですが、Viewでng-showを使ってハンドルする。
<button ng-show="showLoadNext" class="btn btn-info btn-lg" ng-click="loadNext()">More</button>
時間があったら、無限スクロール的に下に行ったら自動的にロードするようにしたいな。