ブログ

encroute.jsのPromiseに関するヒント

このエントリーをはてなブックマークに追加

Webベースアプリテーマで使用する「encroute.js」が提供するAPIの中に、戻り値がPromiseとなっているものがあります。例えば、記事をブックマークするapliko.bookmark.set()です。

Promiseに関する説明は「Promise - JavaScript | MDN」にもあるのですが、ご覧頂くと分かる通り少々長いものです。Promiseは関数を実行した時すぐに値(処理結果)が分からなくても未来のある時点で値や処理結果が分かるようになるオブジェクトである、というのが要点でしょうか。

コールバックとPromiseのコード例

非同期で処理を行うXMLHttpRequestを使用しているgetJSON関数(自作の関数)を例に、コールバックを使用した場合とPromiseを使用した場合のコードを比較してみます。

XMLHttpRequestを使うとサーバーに何かの情報をリクエストし、受信が完了するまでに時間を要します。そのため、データを受信した後の処理をコールバック関数で書くことが多かったと思います。次の例だと、処理が完了した後に実行して欲しいメソッドをgetJSON関数の引数で渡しています。

getJSON(function (data) {
  if (data.totalResults) {
    data.items.forEach(function (item) {
      // 記事の表示処理
    });
  }
});

もしgetJSON関数がPromiseを返す関数の場合、先のコードは以下のようなコードに置き換えられます。

const promise = getJSON();
promise.then(function (data) {
  if (data.totalResults) {
    data.items.forEach(function (item) {
      // 記事の表示処理
    });
  }
});

定数constgetJSON関数が返すPromiseを格納し、then()メソッドでPromiseが成功した時(つまりデータの受信が完了した時)に実行する関数を指定します。(なお、then()メソッドには成功した時の処理と失敗した時の処理をそれぞれ渡すことができます。)

このコードサンプルをご覧頂くと、Promiseは難しいものではないことがお分かり頂けるのではないでしょうか。

Promiseを使う利点

コールバックを使う場合とPromiseを使う場合でコードがほとんど変わらないのであればコールバックで良いのでは?と思われるかもしれません。しかし、PromiseはjQueryでコードを書く時によく利用するようなメソッドチェーン(連鎖)ができるので、例えば「予め記憶したユーザー名・パスワードをフォームに自動入力する」という連続して処理する必要がある2つの非同期処理を書いた時、とても見やすいコードになります。

(function ($) {
  const serviceId = "jp.example.apliko";
  const storageKey = "username";
  (function () {
    // アプリ内に保存済みログイン情報のロード
    const promise = apliko.storage.get(storageKey);
    promise
      .then(
        function (id) {
          // ログイン情報のロードに成功した
          $("#loginId").val(id);
          // 次にアプリ内に保存済みのパスワードのロードを実行する
          return apliko.securedata.get(serviceId, id)
        },
        function () {
          // ログイン情報のロードに失敗した
        }
      )
      .then(
        function (password) {
          // パスワードのロードに成功した
          $("#loginPassword").val(password);
          apliko.progresshud.hide();
        },
        function () {
          // パスワードのロードに失敗した
        }
      );
  }());
}(jQuery));

もし上記の処理をコールバックで書くと、ネストが深くなったり、失敗した時の処理が入り組んだりとコードが読みづらくなってしまいます。(下記の例は成功した時の処理のみ記述しています。)

apliko.storage.get(storageKey, function (id) {
  $("#loginId").val(id);
  apliko.securedata.get(serviceId, id, function (password) {
    $("#loginPassword").val(password);
    apliko.progresshud.hide();
  });
});

まとめ

Webベースアプリの難しい点は「JavaScript」を書かなければいけない点であると考えています。ただ、フロントエンド界隈でもてはやされる「React」などの少しハードルが高い知識は必要なく、jQueryを使用して処理を書くことができるレベルであれば十分と思われます。

実装について不明な点があればフィードバックを頂ければと思います。ブログ等でご紹介、もしくは個別に対応させていただきます。