JavaScript の Promise で Movable Type の Data API から取得した非同期通信データを処理する


※JavaScript のPromise について、勉強がてら記述しました。誤記などありましたらご指摘ください。

Movable Type の Data API からJSONを取得。
取得した データを、JavaScriptで加工して、表示したい。利用したい。
そんなシチュエーションがあると思います。

例として、API経由で取得したデータを、別関数に引き渡すというシチュエーションで考えてみます。

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script>

// Movable Type のData APIから、記事データを取得して、変数listに格納

 const list =  $.ajax('http://your-mt/mt-data-api.cgi/v3/sites/site_id/entries');

// 変数listを表示

 console.log(list);

</script>

このコードでは、Data API 経由で取得した記事データを、console.logで表示しようとしています。しかし、上記の実行結果は以下のようになり、期待通りに記事のデータを表示できません。

これは

  • JavaScript で Data APIを利用するときは、非同期通信で処理を行っている
  • JavaScript は、非同期通信のレスポンスを待たずに処理を実行する
  • 結果として、Data API から取得したデータを受け取る前に、console.logが実行済になってしまう

ことから起こる現象となります。

非同期通信を行っている最中(readyState が 1 の状態) 、つまり通信中の状態で、データを完全に取得する前に console.logを実行してしまい、記事データが期待通りに表示されない状態となります。

JavaScriptでは、非同期通信で取得したデータを処理するために Promise という概念があります。Promise を利用すると、Data API で取得したデータを上手く処理することができます。

Promiseのメリット

Promiseは、ECMAScript2015 から標準仕様として採用されています。

Promise を使うと、JavaScript の非同期通信の結果を待って、次の処理にデータを引き渡すことができます。

Promise については、以下のドキュメントが非常に詳しいため、こちらをご参照ください。

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Promise
http://azu.github.io/promises-book/

※Promise は各種ブラウザで利用できますが、IEではサポートされていません。

Promise を使って、Data APIから取得したデータをうまく処理する

実際にPromise を使って、Movable Type の Data API からデータを取得し、別の関数に渡して表示してみます。

sample-1 JavaScript SDK を使った場合

以下は、Movable Type の Data API 用 JavaScript SDKを使い、console.logにデータを渡して表示する例です。JavaScript SDK のラッパー関数[getEntries]を定義して、Promise のオブジェクトを生成します。Data API との通信が終わったら、次の関数であるconsole.logに値を渡して、表示します。

  <script src="http://your-mt/mt-static/data-api/v3/js/mt-data-api.js"></script>
  <script>

    const api = new MT.DataAPI({
      baseUrl: "http://your-mt/mt-data-api.cgi",
      clientId: "your-client-id"
    });

// MTのブログIDを変数 siteId に格納
    const siteId = IDの数字;

    function getEntries() {
      return new Promise((resolve, reject) => {
        api.listEntries(siteId, function(response) {
          resolve(response);
        });
      });
    }

    getEntries().then(function(response) {
      console.log(response);
    });

</script>

上記のコードの実行すると、以下のように、JavaScript のオブジェクトデータが表示されます。非同期通信の処理を待って、取得したデータを次の関数に引き渡しできていることがわかります。

sample-2 jQueryを使った場合

jQueryを使った場合は、以下のようなコードになります。
実行結果は、sample-1と同じです。

  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
  <script>

    function getEntries() {
      return new Promise((resolve, reject) => {
        const response = $.ajax('http://your-mt/mt-data-api.cgi/v3/sites/site_id/entries')
        resolve(response);
      });
    }
    getEntries().then(function(response) {
      console.log(response);
    });

</script>

sample-3 Promise.resolve を使う

jQueryのajax関数は、Thenable なオブジェクトを返します。このため、Promise のショートカットである Promise.resolve を使った書き方ができます。

  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
  <script>
    const list = $.ajax('http://your-mt/mt-data-api.cgi/v3/sites/site_id/entries');
    Promise.resolve(list).then(function(response) {
      console.log(response);
    });
  </script>

sample-2 よりも、少しスッキリした書き方ができることがわかります。この実行結果は、sample-1,
sample-2 と同じとなります。

今回使った、Movable Type Data API のエンドポイントについては、以下をご参照ください。

https://www.movabletype.jp/developers/data-api/
https://www.movabletype.jp/developers/data-api/v3-reference.html#entries
https://github.com/movabletype/mt-data-api-sdk-js/wiki/DataAPI-SDK-japanese-MT.DataAPI