ES6のPromiseとSymbolの実践的活用

Promiseによる非同期処理の改善

従来のコールバック関数では、複数の非同期操作を順序通りに実行する際に「コールバックヘリックス」が発生し、コードの可読性が低下していました。ES6で導入されたPromiseは、この問題を解決するための主要な仕組みです。

<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.16.2/axios.min.js"></script>
<script>
  // GitHubのユーザー一覧を取得
  axios.get('https://api.github.com/users')
    .then(response => {
      const userName = response.data[0].login;
      // ユーザーのリポジトリ情報を取得
      return axios.get(`https://api.github.com/users/${userName}/repos`);
    })
    .then(reposResponse => {
      console.log('リポジトリ一覧:', reposResponse.data);
    })
    .catch(error => {
      console.error('エラー:', error.response ? error.response.data : error.message);
    });
</script>

複数の非同期処理を統合する: Promise.all

複数のPromiseを同時に実行し、すべてが完了した時点で処理を行う場合、Promise.allが便利です。すべてのプロミスが成功すると、結果の配列が返され、少なくとも一つが失敗すると全体が失敗します。

const fetchUser = axios.get('https://api.github.com/users');
const fetchOrg = axios.get('https://api.github.com/orgs/github');

Promise.all([fetchUser, fetchOrg])
  .then(results => {
    console.log('ユーザー情報:', results[0].data);
    console.log('組織情報:', results[1].data);
  })
  .catch(err => {
    console.error('一部のリクエストが失敗しました:', err);
  });

Symbolによるユニークなキー管理

オブジェクトのプロパティ名が重複するリスクがある場合、Symbolは一意の識別子を生成するための手段です。これは特にライブラリ開発や内部状態の管理に有用です。

const key1 = Symbol('internal');
const key2 = Symbol('internal');

console.log(key1 === key2); // false

const obj = {};
obj[key1] = '秘密のデータ';

// シンボルは通常のループでは見えない
for (const k in obj) {
  console.log(k); // 空出力(シンボルキーは対象外)
}

// ただし、Object.getOwnPropertySymbolsでアクセス可能
console.log(Object.getOwnPropertySymbols(obj)); // [Symbol(internal)]

ES6の新しい構文を利用可能な環境へ変換: Babel

現代のJavaScript(ES6+)の機能は、古いブラウザではサポートされていないため、Babelのようなトランスパイラを使用して、互換性のあるコードに変換する必要があります。例えば、async/awaitlet/constなども変換対象です。

// 変換前のコード
const fetchData = async () => {
  const res = await axios.get('/api/data');
  return res.data;
};

// 変換後のコード(例:Babel出力)
var fetchData = function () {
  var _this = this;
  return _regeneratorRuntime.async(function (_context) {
    while (1) {
      switch (_context.prev = _context.next) {
        case 0:
          _context.next = 2;
          return axios.get('/api/data');
        case 2:
          return _context.abrupt("return", _context.sent.data);
        default:
          if (_context.prev && _context.stopPage) {
            throw _context.error;
          }
      }
    }
  }, null, null, null, _this);
};

古くから使われている環境でも動作させる: Polyfill

特定の機能が利用できない環境では、polyfillによりその振る舞いを再現できます。たとえば、PromiseArray.fromなどのグローバルメソッドは、core-jses-shimsを使って追加可能です。

<script src="https://cdn.jsdelivr.net/npm/core-js@3.25.2/minified.js"></script>
<script>
  // Promiseが存在しない環境でも動作するように補完
  if (typeof Promise === 'undefined') {
    // polyfillの読み込み後、自動的に置き換えられる
  }

  // これ以降、Promiseが使える
  new Promise((resolve) => {
    setTimeout(() => resolve('完了'), 1000);
  }).then(console.log);
</script>

タグ: Promise symbol Babel Polyfill Axios

9月6日 12:31 投稿