0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[Javascript] Promiseに関する基本事項のまとめ

Last updated at Posted at 2025-03-08

JavaScriptのPromise(カタカナではプロミス)は非同期処理を扱うためのオブジェクトであるが,適切な理解が出来ていなかった.
そこで,以下に調べた事を纏めた.

In a nutshell

JavaScriptのPromiseは,非同期処理を管理し,成功(resolved)または失敗(rejected)を扱うオブジェクトである.then()catch()を用いたチェイニング,async/awaitによる簡潔な記述,Promise.all()Promise.race()による複数の非同期処理の制御が可能.エラーハンドリングやfinally()を活用し,信頼性の高い非同期処理を実装できる.


基本的な構造

let promise = new Promise((resolve, reject) => {
  // 非同期処理が成功した場合,resolve()を呼び出す
  let success = true; // この値を元に成功か失敗を決める
  if (success) {
    resolve("成功しました");
  } else {
    reject("失敗しました");
  }
});

then()catch()

Promiseは非同期処理が完了した後に結果を処理するためのメソッドを提供する.then()は成功時に実行され,catch()はエラー時に実行される.

promise
  .then((result) => {
    console.log(result); // 成功時の処理
  })
  .catch((error) => {
    console.log(error); // 失敗時の処理
  });

async/await構文

Promiseの使用は,asyncこうぶnとawaitを使うことでさらに簡潔に書くことができる.awaitPromiseが解決されるのを待つため,非同期処理を同期的に記述できる.


async function example() {
  try {
    let result = await promise; // Promiseが解決されるまで待つ
    console.log(result);
  } catch (error) {
    console.log(error);
  }
}

example();

Promiseの状態

Pending: Promiseがまだ解決されていない状態.
Resolved(Fulfilled): 非同期処理が成功し,resolve()が呼ばれた状態.
Rejected: 非同期処理が失敗し,reject()が呼ばれた状態.

複数のPromiseを扱う

複数のPromiseを扱うためには,Promise.all()Promise.race()を使う.

Promise.all()Promise.race() の違い

両方とも,複数のPromiseを扱うためのメソッドだが,それぞれの挙動には重要な違いがある.
Promise.all()は全ての非同期処理の完了を待つのに対し,Promise.race()は最初に完了した処理を優先する.

Promise.all()

全ての非同期処理が正常に完了することが求められる場合に使用する.
Promise.all()は,渡されたすべてのPromiseが成功するまで待機し,全てのPromiseが解決されたときに,全ての結果を配列として返す.もし,いずれかのPromiseが失敗(拒否)した場合,最初に失敗したPromiseが返すエラーで処理が終了する.

例えば,複数のAPIリクエストを並行して実行し,すべてのデータを一度に処理する際に役立つ.

let p1 = Promise.resolve(3);
let p2 = Promise.resolve(4);
let p3 = Promise.resolve(5);

Promise.all([p1, p2, p3])
  .then((values) => {
    console.log(values); // [3, 4, 5]
  })
  .catch((error) => {
    console.log(error); // 一つでも失敗すればエラー
  });

Promise.race()

例えば,複数のデータ取得方法のうち,最も早くデータが返ってきた方法を選びたい場合などに便利.

一方,Promise.race()は,渡された複数のPromiseの中で最初に解決(成功または失敗)したPromiseの結果を返す.これにより,最初に完了した非同期処理の結果を迅速に取得することができる.Promise.race()はどれか一つのPromiseが解決または拒否された時点で処理が終了するため,処理速度が早い結果を求める場合に使用される.

let p1 = new Promise((resolve, reject) => setTimeout(resolve, 500, 'p1'));
let p2 = new Promise((resolve, reject) => setTimeout(resolve, 100, 'p2'));

Promise.race([p1, p2])
  .then((value) => {
    console.log(value); // 'p2'(最初に解決したPromise)
  })
  .catch((error) => {
    console.log(error);
  });

Promiseのチェイニング

Promiseは,then()メソッドをチェーンして複数の非同期処理を順番に実行することができる.これにより,複雑な非同期フローを扱いやすくなる.次の処理が前の処理の結果に依存する場合に役立つ.

let promise1 = Promise.resolve(5);

promise1
  .then((result) => {
    console.log(result); // 5
    return result * 2;
  })
  .then((result) => {
    console.log(result); // 10
    return result + 3;
  })
  .then((result) => {
    console.log(result); // 13
  })
  .catch((error) => {
    console.log(error);
  });

finally()メソッド

finally()メソッドは,Promiseが成功または失敗に関係なく必ず実行される処理を指定できる.例えば,リソースの解放や終了処理など,成功・失敗に関わらず必ず実行したい処理に使用する.

let promise2 = Promise.resolve(10);

promise2
  .then((result) => {
    console.log(result); // 10
    return result * 3;
  })
  .finally(() => {
    console.log('完了処理'); // 成功・失敗に関わらず実行される
  });

Promiseのエラーハンドリング

複数のPromiseを扱う際,エラーハンドリングに注意が必要.catch()は通常,Promiseのチェーンの最後にエラーをキャッチするが,Promise.all()などで複数のPromiseが失敗した場合,最初に失敗したPromiseがエラーを返す.この場合,残りのPromiseがどうなるかも理解しておく必要がある.


let p1 = Promise.resolve(3);
let p2 = Promise.reject('エラー発生');
let p3 = Promise.resolve(5);

Promise.all([p1, p2, p3])
  .then((values) => {
    console.log(values);
  })
  .catch((error) => {
    console.log(error); // 'エラー発生'
  });

非同期処理の並列実行

Promise.all()はすべてのPromiseが成功するまで待機するが,すべてのPromiseが非同期に実行されるため,並列で処理を実行できる.大量の非同期処理を一度に行いたい場合に有効.

let promise1 = fetch('https://api.example.com/data1');
let promise2 = fetch('https://api.example.com/data2');

Promise.all([promise1, promise2])
  .then((responses) => {
    console.log('両方のリクエストが完了しました');
  })
  .catch((error) => {
    console.log('エラー:', error);
  });

Promiseの用途と実際の使用例

Promiseは,例えば非同期API呼び出し,ファイルの読み書き,タイマーやデータベースのクエリなどでよく使用される.実際の開発において,Promiseを使うことで非同期コードをシンプルで理解しやすいコードにできる.

fetch('https://api.example.com/data')
  .then((response) => response.json())
  .then((data) => {
    console.log(data);
  })
  .catch((error) => {
    console.log('エラー:', error);
  });

Summary

  • Promiseは非同期処理の成功・失敗を管理するオブジェクトであり,pendingresolvedrejectedの3つの状態を持つ.
  • then()は成功時,catch()は失敗時,finally()は成功・失敗に関係なく実行される.
  • async/awaitを使うことで,非同期処理をより簡潔に記述できる.
  • Promise.all()はすべてのPromiseが完了するまで待機し,Promise.race()は最初に完了したPromiseの結果を返す.
  • Promiseのチェイニングを活用することで,複数の非同期処理を順番に実行できる.
  • PromiseはAPI通信,ファイル操作,タイマー処理など,さまざまな非同期処理に利用される.

参考文献

0
0
1

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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?