前提・実現したいこと
カーリルというサイトのAPIから図書館のデータを取得する機能を実装しています。
システムID(図書管理システムのユニークID)と本が持つ固有のISBN番号をURLに入れることで、指定の本がその図書館で取り扱っているか、またその本の貸し出し状況を取得したいです。
以下リクエストとレスポンスの例
レスポンスにcontinue
という値があり、0はロード完了、1はロード未完了を表しています。
サイトに記載の通り、1の場合は最低2秒の間隔をあけて再度ロードし、全てのロードが完了することを推奨しております。(当たり前ですが)
私の場合、本を一冊、複数のシステムIDから検索したいので、システムIDを格納したリストからforで取り出し、繰り返し処理内で本を検索するコードを書きました。
最初に一通り検索、その後continue
が1のデータがある限り、そのデータを再ロードし続けるというコードです。
dart
1// 本のISBN 2String isbn = '9784478025819'; 3// システムID 4List<String> systemIdList = []; 5// システムIDごとのレスポンスのリスト 6List<LibraryDataHasBook> bookDataResult = []; 7 8// 関数 9// ISNBを使って図書館を検索 10Future<dynamic> getLibraryUseISNB({String? systemId, String? session}) async { 11 Uri url; 12 if (session != null && systemId == null) { 13 url = Uri.parse( 14 'https://api.calil.jp/check?session=$session&format=json&callback=no'); 15 } else { 16 url = Uri.parse( 17 'https://api.calil.jp/check?appkey=$apiKey&isbn=$isbn&systemid=$systemId&format=json&callback=no'); 18 } 19 http.Response _response = await http.get(url); 20 if (_response.statusCode == 200) { 21 return jsonDecode(_response.body); 22 } else { 23 print('エラー発生。エラーコード:${_response.statusCode}'); 24 return null; 25 } 26} 27 28// 全てのレスポンスのロードが完了するまで再ロードする 29Future<dynamic> getCompletedLoadingSearchResult() async { 30 var results = []; 31 for (var systemId in systemIdList) { 32 // レスポンス取得 33 final response = await getLibraryUseISNB(systemId: systemId); 34 results.add(response); 35 } 36 37 // ロードが未完のデータがあればそこだけ再実行 38 while (results.where((result) => result['continue'] == 1).isNotEmpty) { 39 print('continue = 1 のため再取得開始'); 40 // 5秒待つ 41 await Future.delayed(const Duration(seconds: 5)); 42 // continue=1のデータのみ再度実行 43 results.asMap().forEach((index, result) async { 44 if (result['continue'] == 1) { 45 results[index] = await getLibraryUseISNB(session: result['session']); 46 } 47 }); 48 } 49 50 return results; 51} 52 53// システムIDを使って本を検索しモデル化してリストを更新 54Future<void> searchAllBookData() async { 55 List<LibraryDataHasBook> list = []; 56 // ロードを完了したレスポンスのリストを取得 57 final response = await getCompletedLoadingSearchResult(); 58 var index = 0; 59 // モデル化 60 for (var data in response) { 61 var libKey = systemIdList[index]; 62 list.add(LibraryDataHasBook( 63 systemId: libKey, 64 status: data['books'][isbn][libKey]['status'], 65 libkey: data['books'][isbn][libKey]['libkey'], 66 url: data['books'][isbn][libKey]['reserveurl'])); 67 index++; 68 } 69 bookDataResult = list; 70} 71 72 73// テスト 74void main() { 75 76 test('システムIDごとに本の検索', () async { 77 // システムIDのリスト 78 systemIdList = [ 79 'Kanagawa_Sagamihara', 80 'Univ_Azabu', 81 'Special_Jaxa', 82 'Univ_Aoyamagakuin', 83 'Univ_Kitasato', 84 'Univ_Obirin', 85 'Univ_Joshibi', 86 'Tokyo_Machida', 87 'Univ_Yamazaki', 88 'Tokyo_Hachioji', 89 'Univ_Tmu', 90 'Univ_Otsuma', 91 'Univ_Salesio', 92 'Tokyo_Tama', 93 'Univ_Sagami_Wu', 94 'Univ_Tamabi', 95 'Kanagawa_Atsugi', 96 'Kanagawa_Zama', 97 'Univ_Toyaku', 98 'Univ_Keisen', 99 'Univ_Chuo', 100 'Univ_Yamano', 101 'Tokyo_Hino', 102 'Kanagawa_Aikawa', 103 'Univ_Teu', 104 'Univ_Meisei', 105 'Univ_Zokei', 106 'Univ_Teikyo', 107 'Univ_Kokushikan', 108 'Kanagawa_Yamato', 109 'Univ_Kait', 110 'Univ_Nms', 111 'Kanagawa_Ebina', 112 'Univ_Tamagawa', 113 'Univ_Jissen' 114 ]; 115 116 // 本を検索 117 await searchAllBookData(); 118 // 中身を確認するコード 119 bookDataResult.asMap().forEach((int i, LibraryDataHasBook data) { 120 print('no.${i + 1}----------'); 121 print(""" 122 systemid: ${data.systemId} 123 status: ${data.status} 124 url: ${data.url} 125 libkey: ${data.libkey} 126 """); 127 }); 128 }); 129}
発生している問題・エラーメッセージ
ロードが完了するまで繰り返し実行しているのですが、何故か3回目で頻繁にエラーが発生します。
カーネルにエラーコード503についての補足が見つからなかったので調べましたが、一般的に503は『一時的なアクセス不可の状態』とのことでした。
/Users/user/flutter_dev/flutter/bin/flutter --no-color test --machine --start-paused --plain-name システムIDごとに本の検索 test/get_response.dart Testing started at 14:58 ... continue = 1 のため再取得開始 continue = 1 のため再取得開始 ←2回目までは実行できてる? エラー発生。エラーコード:503 エラー発生。エラーコード:503 エラー発生。エラーコード:503 エラー発生。エラーコード:503 エラー発生。エラーコード:503 エラー発生。エラーコード:503 エラー発生。エラーコード:503 エラー発生。エラーコード:503 エラー発生。エラーコード:503 エラー発生。エラーコード:503 エラー発生。エラーコード:503 エラー発生。エラーコード:503 エラー発生。エラーコード:503 エラー発生。エラーコード:503 エラー発生。エラーコード:503 エラー発生。エラーコード:503 エラー発生。エラーコード:503 エラー発生。エラーコード:503 エラー発生。エラーコード:503 continue = 1 のため再取得開始 dart:core Object.noSuchMethod test/get_response.dart 134:17 getCompletedLoadingSearchResult.<fn> test/get_response.dart 133:29 getCompletedLoadingSearchResult.<fn> dart:_internal ListMapView.forEach test/get_response.dart 133:21 getCompletedLoadingSearchResult ===== asynchronous gap =========================== dart:async _completeOnAsyncError test/get_response.dart getCompletedLoadingSearchResult.<fn> test/get_response.dart 133:29 getCompletedLoadingSearchResult.<fn> dart:_internal ListMapView.forEach test/get_response.dart 133:21 getCompletedLoadingSearchResult ===== asynchronous gap =========================== dart:async _asyncThenWrapperHelper test/get_response.dart 146:26 searchAllBookData test/get_response.dart 344:11 main.<fn> test/get_response.dart 305:25 main.<fn> NoSuchMethodError: The method '[]' was called on null. Receiver: null Tried calling: []("continue") // 以下、似たようなエラー文のため省略
試したこと
・時間をおいて再実行 → 成功するケースもあれば失敗するケースもあり再現性がない
・別の本を検索した後で再実行 → 同上
・待機時間を5秒〜15秒の間隔で試したが変化なし
・たまに一発で成功するケースもある
以上よろしくお願いします。
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。