JavaScript

JavaScriptのアップデート:Promise.any() の標準化

JavaScriptは、開発者にとって非常に強力な言語であり、その機能は年々進化しています。特に、非同期処理を扱うPromiseオブジェクトは、現代のWeb開発において不可欠な要素となっています。今回のアップデートでは、Promise.any()が標準化され、その使い方や実装例について詳しく解説します。

Promise.any()とは?

Promise.any()は、JavaScriptのPromiseオブジェクトの新しいメソッドであり、複数のPromiseのいずれかが成功するまで待機し、最初に成功したPromiseの結果を返します。全てのPromiseが失敗した場合は、AggregateErrorを投げます。このメソッドは、複数の非同期処理の中から最初に成功した結果を得たい場合に非常に便利です。

使用例

以下に、Promise.any()の簡単な使用例を示します。

const promise1 = Promise.reject('エラー1');
const promise2 = new Promise((resolve) => setTimeout(resolve, 100, '成功2'));
const promise3 = new Promise((resolve) => setTimeout(resolve, 500, '成功3'));

Promise.any([promise1, promise2, promise3])
  .then((result) => {
    console.log(result); // '成功2' が出力される
  })
  .catch((error) => {
    console.error(error);
  });

 

この例では、最初のPromiseは失敗し、2番目のPromiseが成功します。Promise.any()は、成功した結果を受け取り、コンソールに出力します。

Promise.any()の動作と特徴

Promise.any()の動作は非常にシンプルですが、その背後にはいくつかの重要な特徴があります。

  1. 最初の成功を返す: Promise.any()は、配列内のPromiseのうち最初に成功したものの結果を返します。これは、複数のAPIリクエストや複数のデータベースクエリを行う際に、最も迅速な結果を得るために非常に有用です。
  2. 全てのPromiseが失敗した場合: 配列内の全てのPromiseが拒否された場合、Promise.any()はAggregateErrorを投げます。AggregateErrorは、複数のエラーを保持できる新しいエラーオブジェクトです。これにより、失敗した理由を一度に処理できます。

AggregateErrorの例

const promise1 = Promise.reject('エラー1');
const promise2 = Promise.reject('エラー2');
const promise3 = Promise.reject('エラー3');

Promise.any([promise1, promise2, promise3])
  .then((result) => {
    console.log(result);
  })
  .catch((error) => {
    if (error instanceof AggregateError) {
      console.error('全てのPromiseが拒否されました:');
      error.errors.forEach((err) => console.error(err));
    }
  });

 

この例では、全てのPromiseが失敗したため、AggregateErrorがキャッチされ、失敗した理由が出力されます。

Promise.any()の実用的な活用例

Promise.any()は、特にAPI呼び出しやデータベースクエリのような非同期処理で非常に役立ちます。ここでは、いくつかの実用的な活用例を示します。

API呼び出しのフォールバック

例えば、複数のAPIエンドポイントからデータを取得する場合、どれか一つでも成功すれば良い場合があります。以下はそのようなシナリオの実装例です。

const fetchFromAPI1 = fetch('https://api.example.com/data1').then(response => response.json());
const fetchFromAPI2 = fetch('https://api.example.com/data2').then(response => response.json());
const fetchFromAPI3 = fetch('https://api.example.com/data3').then(response => response.json());

Promise.any([fetchFromAPI1, fetchFromAPI2, fetchFromAPI3])
  .then((data) => {
    console.log('取得したデータ:', data);
  })
  .catch((error) => {
    console.error('全てのAPI呼び出しが失敗しました:', error);
  });

 

この例では、3つのAPIからデータを取得し、最初に成功したものの結果をログに出力します。

ユーザー入力のバリデーション

また、ユーザーからの入力を複数のバリデーション関数で検証する場合にも利用できます。最初に成功したバリデーションを採用することができます。

const validateEmail = (email) => Promise.resolve(/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email));
const validatePhoneNumber = (phone) => Promise.resolve(/^\d{10}$/.test(phone));
const validateUsername = (username) => Promise.resolve(username.length >= 3);

const userInput = {
  email: 'example@example.com',
  phone: '1234567890',
  username: 'user'
};

Promise.any([
  validateEmail(userInput.email),
  validatePhoneNumber(userInput.phone),
  validateUsername(userInput.username)
])
.then((result) => {
  console.log('少なくとも1つのバリデーションに合格しました:', result);
})
.catch((error) => {
  console.error('全てのバリデーションに失敗しました:', error);
});

 

このコードは、ユーザーの入力に対して複数のバリデーションを行い、最初に合格したものの結果を出力します。

Promise.any()は、複数の非同期処理を扱う際に非常に便利なメソッドです。最初に成功したPromiseの結果を取得できるため、API呼び出しやデータベースクエリなど、さまざまな場面での活用が期待されます。AggregateErrorを通じて全てのエラーを一括で扱える点も大きな利点です。

ABOUT ME
りん
沖縄から福岡に移住。QA/Webデザイナー/SE/フリーランス/SE人事など。趣味や好きなことをブログにまとめてます。