検索
ホームページウェブフロントエンドjsチュートリアルJavaScript 非同期パターンをマスターする: コールバックから非同期/待機まで

Mastering JavaScript Async Patterns: From Callbacks to Async/Await

私が初めて非同期 JavaScript に出会ったとき、コールバックに苦労し、Promise が内部でどのように機能するのか全く分かりませんでした。時間が経つにつれて、Promise と async/await について学ぶことで、コーディングへのアプローチが変わり、はるかに管理しやすくなりました。このブログでは、これらの非同期パターンを段階的に検討し、開発プロセスを合理化し、コードをよりクリーンかつ効率的にする方法を明らかにします。これらの概念を一緒に掘り下げて明らかにしましょう!

非同期 JavaScript を学ぶ必要があるのはなぜですか?

現代の Web 開発には、非同期 JavaScript を学習することが不可欠です。これにより、API リクエストなどのタスクを効率的に処理できるようになり、アプリケーションの応答性と高速性が維持されます。 Promise や async/await などの非同期テクニックを習得することは、スケーラブルなアプリケーションを構築するだけでなく、JavaScript の面接で成功するためにも重要であり、これらの概念を理解することが重要な焦点となることがよくあります。非同期 JavaScript をマスターすることで、コーディング スキルを強化し、現実世界の課題に備えることができます。

非同期パターンとは何ですか?

JavaScript の非同期パターンは、アプリケーションをフリーズさせることなく、サーバーからのデータの取得など、時間のかかるタスクを処理するために使用される手法です。当初、開発者はコールバックを使用してこれらのタスクを管理していましたが、このアプローチでは、「コールバック地獄」として知られる複雑で読みにくいコードが生じることがよくありました。これを簡素化するために Promise が導入され、アクションを連鎖させてエラーをより適切に処理することにより、非同期操作を処理するためのよりクリーンな方法が提供されました。進化は async/await にも続きました。これにより、同期コードのように見え、動作する非同期コードを作成できるようになり、読みやすく、保守しやすくなります。これらのパターンは、効率的で応答性の高いアプリケーションを構築するために重要であり、最新の JavaScript 開発の基本です。このブログでは、これらの概念についてさらに詳しく説明します。

コールバックとは何ですか?

コールバック は、受信関数がある時点でコールバックを実行することを目的として、他の関数に引数として渡す関数です。これは、サーバーからデータを取得した後や計算を終了した後など、特定のタスクの完了後に一部のコードを確実に実行する必要があるシナリオに役立ちます。

コールバックの仕組み:

  1. 関数 (コールバック) を定義します。
  2. この関数を引数として別の関数に渡します。
  3. 受信関数は適切なタイミングでコールバックを実行します。

例 1

function fetchData(callback) {
  // Simulate fetching data with a delay
  setTimeout(() => {
    const data = "Data fetched";
    callback(data); // Call the callback function with the fetched data
  }, 1000);
}

function processData(data) {
  console.log("Processing:", data);
}

fetchData(processData); // fetchData will call processData with the data

例 2

// Function that adds two numbers and uses a callback to return the result
function addNumbers(a, b, callback) {
  const result = a + b;
  callback(result); // Call the callback function with the result
}

// Callback function to handle the result
function displayResult(result) {
  console.log("The result is:", result);
}

// Call addNumbers with the displayResult callback
addNumbers(5, 3, displayResult);

: コールバックは非同期操作の処理に効果的だと思いますが、注意してください。特にネストされたコールバックの場合、コードの複雑さが増すと、コールバック地獄として知られる問題に遭遇する可能性があります。この問題は、コールバックが相互に深くネストされている場合に発生し、可読性の問題が発生し、コードの保守が困難になります。

コールバック地獄

コールバック地獄 (破滅のピラミッド とも呼ばれます) は、複数のネストされたコールバックがある状況を指します。これは、複数の非同期操作を順番に実行する必要があり、各操作が前の操作に依存している場合に発生します。

例:これにより、読み取りや保守が困難な「ピラミッド」構造が作成されます。

fetchData(function(data1) {
  processData1(data1, function(result1) {
    processData2(result1, function(result2) {
      processData3(result2, function(result3) {
        console.log("Final result:", result3);
      });
    });
  });
});

コールバック地獄の問題:

  1. 可読性: コードは読みにくく、理解しにくくなります。
  2. 保守性: 変更やデバッグが困難になります。
  3. エラー処理: エラーの管理は複雑になる場合があります。

コールバックによるエラーの処理

コールバックを使用する場合、error-first コールバック として知られるパターンを使用するのが一般的です。このパターンでは、コールバック関数は最初の引数としてエラーを受け取ります。エラーがない場合、通常、最初の引数は null または未定義であり、実際の結果が 2 番目の引数として提供されます。

function fetchData(callback) {
  setTimeout(() => {
    const error = null; // Or `new Error("Some error occurred")` if there's an error
    const data = "Data fetched";
    callback(error, data); // Pass error and data to the callback
  }, 1000);
}

function processData(error, data) {
  if (error) {
    console.error("Error:", error);
    return;
  }
  console.log("Processing:", data);
}

fetchData(processData); // `processData` will handle both error and data

: コールバックの後、JavaScript で非同期プロセスを処理するために Promise が導入されました。次に、Promise をさらに深く掘り下げ、Promise が内部でどのように機能するかを探っていきます。

約束の概要

Promises は、非同期操作の最終的な完了 (または失敗) とその結果の値を表すオブジェクトです。これらは、コールバックと比較して、非同期コードを処理するためのよりクリーンな方法を提供します。

約束の目的:

  1. Avoid Callback Hell: Promises help manage multiple asynchronous operations without deep nesting.
  2. Improve Readability: Promises provide a more readable way to handle sequences of asynchronous tasks.

Promise States

A Promise can be in one of three states:

  1. Pending: The initial state, before the promise has been resolved or rejected.
  2. Fulfilled: The state when the operation completes successfully, and resolve has been called.
  3. Rejected: The state when the operation fails, and reject has been called.

Note: If you want to explore more, you should check out Understand How Promises Work Under the Hood where I discuss how promises work under the hood.

example 1

// Creating a new promise
const myPromise = new Promise((resolve, reject) => {
  const success = true; // Simulate success or failure
  if (success) {
    resolve("Operation successful!"); // If successful, call resolve
  } else {
    reject("Operation failed!"); // If failed, call reject
  }
});

// Using the promise
myPromise
  .then((message) => {
    console.log(message); // Handle the successful case
  })
  .catch((error) => {
    console.error(error); // Handle the error case
  });

example 2

const examplePromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    const success = Math.random() > 0.5; // Randomly succeed or fail
    if (success) {
      resolve("Success!");
    } else {
      reject("Failure.");
    }
  }, 1000);
});

console.log("Promise state: Pending...");

// To check the state, you would use `.then()` or `.catch()`
examplePromise
  .then((message) => {
    console.log("Promise state: Fulfilled");
    console.log(message);
  })
  .catch((error) => {
    console.log("Promise state: Rejected");
    console.error(error);
  });

Chaining Promises

Chaining allows you to perform multiple asynchronous operations in sequence, with each step depending on the result of the previous one.

Chaining promises is a powerful feature of JavaScript that allows you to perform a sequence of asynchronous operations where each step depends on the result of the previous one. This approach is much cleaner and more readable compared to deeply nested callbacks.

How Promise Chaining Works

Promise chaining involves connecting multiple promises in a sequence. Each promise in the chain executes only after the previous promise is resolved, and the result of each promise can be passed to the next step in the chain.

function step1() {
  return new Promise((resolve) => {
    setTimeout(() => resolve("Step 1 completed"), 1000);
  });
}

function step2(message) {
  return new Promise((resolve) => {
    setTimeout(() => resolve(message + " -> Step 2 completed"), 1000);
  });
}

function step3(message) {
  return new Promise((resolve) => {
    setTimeout(() => resolve(message + " -> Step 3 completed"), 1000);
  });
}

// Chaining the promises
step1()
  .then(result => step2(result))
  .then(result => step3(result))
  .then(finalResult => console.log(finalResult))
  .catch(error => console.error("Error:", error));

Disadvantages of Chaining:
While chaining promises improves readability compared to nested callbacks, it can still become unwieldy if the chain becomes too long or complex. This can lead to readability issues similar to those seen with callback hell.

Note: To address these challenges, async and await were introduced to provide an even more readable and straightforward way to handle asynchronous operations in JavaScript.

Introduction to Async/Await

async and await are keywords introduced in JavaScript to make handling asynchronous code more readable and easier to work with.

  • async: Marks a function as asynchronous. An async function always returns a promise, and it allows the use of await within it.
  • await: Pauses the execution of the async function until the promise resolves, making it easier to work with asynchronous results in a synchronous-like fashion.
async function fetchData() {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve("Data fetched");
    }, 1000);
  });
}

async function getData() {
  const data = await fetchData(); // Wait for fetchData to resolve
  console.log(data); // Logs "Data fetched"
}

getData();

How Async/Await Works

1. Async Functions Always Return a Promise:

No matter what you return from an async function, it will always be wrapped in a promise. For example:

async function example() {
  return "Hello";
}

example().then(console.log); // Logs "Hello"

Even though example() returns a string, it is automatically wrapped in a promise.

2. Await Pauses Execution:

The await keyword pauses the execution of an async function until the promise it is waiting for resolves.

async function example() {
  console.log("Start");
  const result = await new Promise((resolve) => {
    setTimeout(() => {
      resolve("Done");
    }, 1000);
  });
  console.log(result); // Logs "Done" after 1 second
}

example();

In this example:

  • "Start" is logged immediately.
  • The await pauses execution until the promise resolves after 1 second.
  • "Done" is logged after the promise resolves.

Error Handling with Async/Await

Handling errors with async/await is done using try/catch blocks, which makes error handling more intuitive compared to promise chains.

async function fetchData() {
  throw new Error("Something went wrong!");
}

async function getData() {
  try {
    const data = await fetchData();
    console.log(data);
  } catch (error) {
    console.error("Error:", error.message); // Logs "Error: Something went wrong!"
  }
}

getData();

With Promises, you handle errors using .catch():

fetchData()
  .then(data => console.log(data))
  .catch(error => console.error("Error:", error.message));

Using async/await with try/catch often results in cleaner and more readable code.

Combining Async/Await with Promises

You can use async/await with existing promise-based functions seamlessly.

example

function fetchData() {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve("Data fetched");
    }, 1000);
  });
}

async function getData() {
  const data = await fetchData(); // Wait for the promise to resolve
  console.log(data); // Logs "Data fetched"
}

getData();

Best Practices:

  1. 可読性を高めるために async/await を使用します。 複数の非同期操作を扱う場合、async/await を使用すると、コードがより直線的で理解しやすくなります。
  2. Promises と組み合わせる: Promise ベースの関数で async/await を引き続き使用して、複雑な非同期フローをより自然に処理します。
  3. エラー処理: 潜在的なエラーを処理するには、非同期関数では常に try/catch ブロックを使用します。

結論

async と await は、従来の Promise チェーンやコールバックと比較して、非同期操作を処理するためのよりクリーンで読みやすい方法を提供します。同期コードのように見え、動作する非同期コードを作成できるようにすることで、複雑なロジックが簡素化され、try/catch ブロックによるエラー処理が向上します。 Promise で async/await を使用すると、コードがより保守しやすく、理解しやすくなります。

以上がJavaScript 非同期パターンをマスターする: コールバックから非同期/待機までの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
Python vs. JavaScript:学習曲線と使いやすさPython vs. JavaScript:学習曲線と使いやすさApr 16, 2025 am 12:12 AM

Pythonは、スムーズな学習曲線と簡潔な構文を備えた初心者により適しています。 JavaScriptは、急な学習曲線と柔軟な構文を備えたフロントエンド開発に適しています。 1。Python構文は直感的で、データサイエンスやバックエンド開発に適しています。 2。JavaScriptは柔軟で、フロントエンドおよびサーバー側のプログラミングで広く使用されています。

Python vs. JavaScript:コミュニティ、ライブラリ、リソースPython vs. JavaScript:コミュニティ、ライブラリ、リソースApr 15, 2025 am 12:16 AM

PythonとJavaScriptには、コミュニティ、ライブラリ、リソースの観点から、独自の利点と短所があります。 1)Pythonコミュニティはフレンドリーで初心者に適していますが、フロントエンドの開発リソースはJavaScriptほど豊富ではありません。 2)Pythonはデータサイエンスおよび機械学習ライブラリで強力ですが、JavaScriptはフロントエンド開発ライブラリとフレームワークで優れています。 3)どちらも豊富な学習リソースを持っていますが、Pythonは公式文書から始めるのに適していますが、JavaScriptはMDNWebDocsにより優れています。選択は、プロジェクトのニーズと個人的な関心に基づいている必要があります。

C/CからJavaScriptへ:すべてがどのように機能するかC/CからJavaScriptへ:すべてがどのように機能するかApr 14, 2025 am 12:05 AM

C/CからJavaScriptへのシフトには、動的なタイピング、ゴミ収集、非同期プログラミングへの適応が必要です。 1)C/Cは、手動メモリ管理を必要とする静的に型付けられた言語であり、JavaScriptは動的に型付けされ、ごみ収集が自動的に処理されます。 2)C/Cはマシンコードにコンパイルする必要がありますが、JavaScriptは解釈言語です。 3)JavaScriptは、閉鎖、プロトタイプチェーン、約束などの概念を導入します。これにより、柔軟性と非同期プログラミング機能が向上します。

JavaScriptエンジン:実装の比較JavaScriptエンジン:実装の比較Apr 13, 2025 am 12:05 AM

さまざまなJavaScriptエンジンは、各エンジンの実装原則と最適化戦略が異なるため、JavaScriptコードを解析および実行するときに異なる効果をもたらします。 1。語彙分析:ソースコードを語彙ユニットに変換します。 2。文法分析:抽象的な構文ツリーを生成します。 3。最適化とコンパイル:JITコンパイラを介してマシンコードを生成します。 4。実行:マシンコードを実行します。 V8エンジンはインスタントコンピレーションと非表示クラスを通じて最適化され、Spidermonkeyはタイプ推論システムを使用して、同じコードで異なるパフォーマンスパフォーマンスをもたらします。

ブラウザを超えて:現実世界のJavaScriptブラウザを超えて:現実世界のJavaScriptApr 12, 2025 am 12:06 AM

現実世界におけるJavaScriptのアプリケーションには、サーバー側のプログラミング、モバイルアプリケーション開発、モノのインターネット制御が含まれます。 2。モバイルアプリケーションの開発は、ReactNativeを通じて実行され、クロスプラットフォームの展開をサポートします。 3.ハードウェアの相互作用に適したJohnny-Fiveライブラリを介したIoTデバイス制御に使用されます。

next.jsを使用してマルチテナントSaaSアプリケーションを構築する(バックエンド統合)next.jsを使用してマルチテナントSaaSアプリケーションを構築する(バックエンド統合)Apr 11, 2025 am 08:23 AM

私はあなたの日常的な技術ツールを使用して機能的なマルチテナントSaaSアプリケーション(EDTECHアプリ)を作成しましたが、あなたは同じことをすることができます。 まず、マルチテナントSaaSアプリケーションとは何ですか? マルチテナントSaaSアプリケーションを使用すると、Singの複数の顧客にサービスを提供できます

next.jsを使用してマルチテナントSaaSアプリケーションを構築する方法(フロントエンド統合)next.jsを使用してマルチテナントSaaSアプリケーションを構築する方法(フロントエンド統合)Apr 11, 2025 am 08:22 AM

この記事では、許可によって保護されたバックエンドとのフロントエンド統合を示し、next.jsを使用して機能的なedtech SaaSアプリケーションを構築します。 FrontEndはユーザーのアクセス許可を取得してUIの可視性を制御し、APIリクエストがロールベースに付着することを保証します

JavaScript:Web言語の汎用性の調査JavaScript:Web言語の汎用性の調査Apr 11, 2025 am 12:01 AM

JavaScriptは、現代のWeb開発のコア言語であり、その多様性と柔軟性に広く使用されています。 1)フロントエンド開発:DOM操作と最新のフレームワーク(React、Vue.JS、Angularなど)を通じて、動的なWebページとシングルページアプリケーションを構築します。 2)サーバー側の開発:node.jsは、非ブロッキングI/Oモデルを使用して、高い並行性とリアルタイムアプリケーションを処理します。 3)モバイルおよびデスクトップアプリケーション開発:クロスプラットフォーム開発は、反応および電子を通じて実現され、開発効率を向上させます。

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

Dreamweaver Mac版

Dreamweaver Mac版

ビジュアル Web 開発ツール

EditPlus 中国語クラック版

EditPlus 中国語クラック版

サイズが小さく、構文の強調表示、コード プロンプト機能はサポートされていません

AtomエディタMac版ダウンロード

AtomエディタMac版ダウンロード

最も人気のあるオープンソースエディター

VSCode Windows 64 ビットのダウンロード

VSCode Windows 64 ビットのダウンロード

Microsoft によって発売された無料で強力な IDE エディター

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)