0
0

【JavaScript】非同期処理について(Promise, async, await)

Last updated at Posted at 2024-08-07

はじめに

JavaScriptを用いる際に理解しておくべき非同期処理についてまとめました。

非同期処理

  • JavaScriptのコードは、基本的にメインスレッド(UIスレッド)で実行される
  • メインスレッドでは、画面の描画等の処理も実行される
  • ゆえに、メインスレッドに時間のかかる処理(サーバーへのHTTPリクエストなど)がある場合、そこで画面がフリーズしてしまう
  • 非同期処理を用いれば、時間のかかる処理と並行してその他の処理を実行できる
  • そのため、画面フリーズの問題を解決できる
  • 非同期処理は、基本的に並行処理であって、それらはメインスレッドで実行される

Promise

  • Promiseは、現代のJavaScriptにおいて非同期処理を行う際の基礎となるもの
  • fetch()APIなどのPromiseベースのAPIでは、返値としてPromiseオブジェクトを返す
  • 非同期処理を実行すると、すぐにPromiseオブジェクトが返されて、次の処理へ移る
  • Promiseオブジェクトのthen()メソッドにハンドラー関数を渡すと、非同期処理が成功した場合にそのハンドラー関数が実行される
  • Promiseオブジェクトのcatch()メソッドにハンドラー関数を渡すと、非同期処理が失敗した場合にそのハンドラー関数が実行される。つまり、エラー処理を行う
  • then()メソッドもPromiseオブジェクトを返すため、.(ドット)で繋いで非同期処理を連続して行うことができる。非同期処理は、その順番で完了されていく
  • then()メソッドの連鎖の最後にcatch()メソッドを繋ぐと、連鎖の中のいずれかの非同期処理が失敗した場合にエラー処理をすることができる
fetch()を使った例
const fetchPromise = fetch(
  'https://mdn.github.io/learning-area/javascript/apis/fetching-data/can-store/products.json'
);

fetchPromise
  .then(response => {
    if (!response.ok) {
      throw new Error(`error: ${response.status}`);
    }
    return response.json();
  })
  .then(data => {
    console.log(data[0].name);
  })
  .catch(error => {
    console.error(`処理が失敗しました。: ${error}`);
  });

console.log('処理の開始');

  • 上記の例では、fetch()が呼び出されると、fetchPromiseにPromiseオブジェクトが格納され、非同期処理が始まる。この後の非同期処理(HTTPリクエスト及びjson()メソッド)は時間がかかるので、先にconsole.log('処理の開始');が完了することに注意。その後、非同期処理が順に完了して行き、取得したデータの内容が表示される。なお、URLをいじってリクエストを失敗させれば、catch()メソッドの内容が実行される。

Promiseが登場する前

  • Promiseが登場する前には、コールバック関数を用いて非同期処理を実装していた
  • しかし、コールバック関数を受け取るコールバック関数が必要となるなど、ネストが深くなりがちであったため、コードがとても分かり辛いものとなっていた(コールバック地獄)
  • また、ある非同期処理の外側からその非同期処理のエラー処理をすることはできないため、各非同期処理ごとにエラー処理を記述する必要があり、これもコードが分かり辛くなる原因となっていた

async/await

  • asyncキーワードを用いると、Promiseによる非同期処理をさらにシンプルに動作させることができる。
  • 関数の開始時にasync()を追加すると、その関数は非同期関数になる
  • 非同期関数の内部では、Promiseを返す関数を呼び出す前にawaitキーワードを使用することができる。これは、Promiseの結果が決定するまでその関数で処理を待たせ、Promiseの結果を返すか、失敗時の例外を発生させる
  • async及びawaitを用いることで、あたかも通常の同期処理のコードのように記述することができる。エラー処理も通常のtry-catch文のように書ける。
async/awaitを用いた例
async function fetchProducts () {
  try {
    const response = await fetch(
      'https://mdn.github.io/learning-area/javascript/apis/fetching-data/can-store/products.json'
    );
    if (!response.ok) {
      throw new Error(`error: ${response.status}`);
    }
    const data = await response.json();
    console.log(data[0].name);
  } catch (error) {
    console.error(`処理が失敗しました: ${error}`);
  }
}

// これは非同期関数であり、時間がかかる処理なので、この次のconsole.logの処理が先に実行される。
fetchProducts();

console.log('処理の開始');

参考文献

mdn 非同期 JavaScript
JavaScript Primer 非同期処理:Promise/Async Function

0
0
0

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