LoginSignup
2
1

More than 3 years have passed since last update.

Javascript(async/await)で複数APIの非同期処理の結果を取得する

Posted at

複数のIT勉強会イベントのAPIを使ってカレンダー表示しているサイトはいくつもあるけれど、
リスト表示したり、自分が思った通りのレイアウトで出したかったのでJavascriptを使ってAPIからイベント情報を取得した話。

connpassと、atndと、doorkeeperのAPIを非同期で処理しつつ最後に取得した結果をまとめたい。
それぞれのサービスでは1回で全件取得できないので、複数回に分けてAPIを呼ぶ必要があるが、同じサービス内で非同期で処理すると負荷をかけてしまうのが心配なので、同じAPIに対しては同期的に処理したい。

非同期、同期処理はES2017の「async / await」が便利なので使う。IEでは使えない。

APIを読み込んで同期的に結果を変数に格納する場合。

(async () => {
  let events = [];
  let event = [];
  let data = [];

  // connpassのデータ取得
  data = await $.ajax({url: 'connpassのURL', dataType: 'jsonp'});
  event = connpass(data); // 取得したjsonの結果を共通の形式の配列に変換
  events = events.concat(event); // イベント情報の配列に追記 
 
  // atndのデータ取得
  data = await $.ajax({url: 'atndのURL', dataType: 'jsonp'});
  event = atnd(data); // 取得したjsonの結果を共通の形式の配列に変換
  events = events.concat(event); // イベント情報の配列に追記 

  callback(events); // イベント情報の表示を行う処理
 
})();

awaitを入れると同期通信になって戻り値が取れるので便利。

一度に全件取得できないので(APIによって100件単位など)、複数回APIを呼び出す。

(async () => {
  let events = [];
  let event = [];
  let data = [];

  // connpassのデータ取得(100件を10回)
  for (let i = 0; i < 10; i++) {
    data = await $.ajax({url: 'connpassのURL?start=' + (i * 100 + 1), dataType: 'jsonp'});
    event = connpass(data); // 取得したjsonの結果を共通の形式の配列に変換
    events = events.concat(event); // イベント情報の配列に追記 
  }

  // atndのデータ取得(100件を10回)
  for (let i = 0; i < 10; i++) {
    data = await $.ajax({url: 'atndのURL?start=' + (i * 100 + 1), dataType: 'jsonp'});
    event = atnd(data); // 取得したjsonの結果を共通の形式の配列に変換
    events = events.concat(event); // イベント情報の配列に追記 
  } 

  callback(events); // イベント情報の表示を行う処理
 
})();

上記の方法だと、全て20件とも同期的に順番に動いてしまうので、時間がかかってしまう。
connpassと、atndのAPIに対して非同期に動作すれば、10件分の時間に短縮出来る。
全部非同期にすれば1件分の時間で済むはずだが、同じAPIに対して10件分同時アクセスになってしまい、負荷をかけてしまうかも知れないので、同一APIでは同期的にアクセスする。

(async () => {
  let events = [];
  let event = [];
  let data = [];
  let results = [];

  // connpassのデータ取得(100件を10回)
  results.push((async () => {
    for (let i = 0; i < 10; i++) {
      data = await $.ajax({url: 'connpassのURL?start=' + (i * 100 + 1), dataType: 'jsonp'});
      event = connpass(data); // 取得したjsonの結果を共通の形式の配列に変換
      events = events.concat(event); // イベント情報の配列に追記 
    }
  })());

  // atndのデータ取得(100件を10回)  
  results.push((async () => {
    for (let i = 0; i < 10; i++) {
      data = await $.ajax({url: 'atndのURL?start=' + (i * 100 + 1), dataType: 'jsonp'});
      event = atnd(data); // 取得したjsonの結果を共通の形式の配列に変換
      events = events.concat(event); // イベント情報の配列に追記 
    }
  })());

  await Promise.all(results); // 非同期処理の結果をまとめて受け取る。
  callback(events); // イベント情報の表示を行う処理
 
})();

非同期処理の結果を最後にまとめて取得するのにはPromise.allを使用する。
全体のasyncに加えて、API毎にもasyncを指定することで、異なるAPIは非同期で、同一APIでは同期処理になる。
Promise.allで其々の処理を並列で実行して結果を取得する。

参考URL

最終的な成果物は以下の通り

使用したイベントAPIは以下の通り

APIから取得したイベント情報を配列に整形して、FullCalendar.jsのライブラリにセットして、カレンダー表示やリスト表示をおこなっている。
FullCalendar.jsはVersion3まではJQueryを使用していたが、最新のVersion4からJQueryを使用しなくなっている。JQueryを使用してるVersion3までの記事が多いので注意。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1