ホームページ > 記事 > ウェブフロントエンド > 非同期 JavaScript: Promise と Async/Await の詳細
非同期プログラミングは、最新の Web 開発、特に JavaScript において極めて重要です。従来、プログラミング言語はコードを上から下に順番に実行します。ただし、この同期実行モデルは、特にサーバーからのデータの取得、ファイルへのアクセス、複雑な計算の実行などの時間のかかる操作を処理する場合に、非効率につながる可能性があります。非同期プログラミングは、特定のプロセスをメインの実行スレッドから独立して実行できるようにすることで、これらの課題に対処し、それによって Web アプリケーションの応答性とパフォーマンスを向上させます。
本質的にシングルスレッドである JavaScript は、非同期プログラミングを利用して、完了するまで実行スレッドをブロックする操作を管理します。これは、コールバック、Promise、async/await 構文などの機能によって実現され、本質的に完了時間が不確実な操作の処理に役立ちます。 JavaScript で非同期プログラミングを習得することの重要性は、どれだけ強調してもしすぎることはありません。これにより、開発者はよりスムーズで高速、よりインタラクティブな Web エクスペリエンスを作成できるようになります。 Web サイトと Web アプリケーションがますます複雑になり、データ主導型になるにつれて、パフォーマンスを維持し、シームレスなユーザー エクスペリエンスを提供するには、非同期操作を効果的に処理することが重要です。
本質的に、非同期プログラミングは、メインスレッドのブロックを防ぐことで Web アプリケーションのパフォーマンスを最適化するだけでなく、コードベースのスケーラビリティと保守性にも大きく貢献します。この主題をさらに深く掘り下げながら、非同期操作を処理するために JavaScript が提供するメカニズムとパターン、そしてそれらが現代の Web 開発者のツールキットに不可欠である理由を探っていきます。
賑やかなコーヒーショップのカウンターで注文するところを想像してみてください。飲み物が準備されるのを待つ代わりに、座って雑誌を読みます。その間、バリスタはあなたの注文に応えます。コーヒーの準備ができたら、バリスタから電話がかかってきますので、コーヒーを取りに来てください。このシナリオは、JavaScript での非同期操作の仕組みに似ています。
JavaScript における非同期操作は、注文をキッチンに送信するようなものです。立って料理が終わるのを待つ必要はありません。カフェで本を読んだり、友達とおしゃべりしたり、音楽を楽しんだりすることができます。ご注文の準備ができましたらお知らせいたしますので、お楽しみください。同様に、非同期 JavaScript を使用すると、API 呼び出しやファイル操作などのタスクをバックグラウンドで実行できます。カフェにいるあなたと同じように、メイン プログラムはブロックされません。引き続き実行され、他のユーザー入力またはアクションに応答します。
API 呼び出し: これらは、映画を見ながら宅配サービスに食べ物を注文するようなものです。食べ物を待つために映画を一時停止する必要はありません。観察を続けると、ドアベルが鳴ると、食べ物が届きます。 Web 開発では、サーバーへのデータのリクエストも同様に機能します。データを要求してサイトとの対話を続けると、データが到着するとデータが表示されます。
fetch('https://jsonplaceholder.typicode.com/todos/1') .then(response => response.json()) // Convert the response to JSON .then(data => console.log(data)) // Log the data .catch(error => console.error('Error:', error)); // Handle any errors
ファイル操作: これは、机を片付けている間にドキュメントを送信してプリンターで印刷するのと似ています。すべての書類が届くまでプリンターのそばに立つ必要はありません。他のタスクを続けます。同様に、JavaScript でのファイル操作 (特に Node.js などのプラットフォーム) では、ファイルの読み取りまたは書き込み操作を開始してから、他のタスクに移り、操作が完了すると通知を受け取ることができます。
const fs = require('fs'); fs.readFile('example.txt', 'utf8', (err, data) => { if (err) { console.error('Error reading the file:', err); return; } console.log(data); // Log the contents of the file });
タイマーと遅延: JavaScript で setTimeout() または setInterval() を使用することは、ケーキを焼くときにオーブン タイマーを設定するのと似ています。タイマーをセットしてオーブンを放置し、フロスティングを作りながら作業を続けます。タイマーによって他のアクティビティが停止されることはありません。次のステップに進むタイミングを通知するだけです。
setTimeout(() => { console.log('This message appears after 2 seconds!'); }, 2000);
イベント リスナー: 動きを検出するとベルを鳴らすモーション センサーを庭に設置することを想像してください。これがイベントリスナーの仕組みです。特定のイベント (クリックやキーストロークなど) を監視するように設定すると、アプリケーションの他の操作を妨げることなく、それに応じて関連する機能が実行されます。
document.getElementById('myButton').addEventListener('click', () => { console.log('Button was clicked!'); });
Imagine you're at a carnival and just tossed a ring towards a bottle, aiming to hook it. At that moment, three outcomes are possible: the ring lands perfectly (success), misses entirely (failure), or is still spinning in the air (pending). In JavaScript, this scenario is analogous to a Promise. A Promise is an object that represents the eventual completion or failure of an asynchronous operation. It’s like making a bet on whether the ring will land.
Pending: The Promise is initially in the "pending" state. It's uncertain, like the ring spinning in the air.
Fulfilled: If the asynchronous operation completes successfully, the Promise is "fulfilled." Think of this as the ring landing on the bottle.
Rejected: If the operation fails or encounters an error, the Promise is "rejected." This is akin to the ring missing the target.
Here is how you can create a promise for the above example:
const ringToss = new Promise((resolve, reject) => { let hasLanded = Math.random() > 0.5; // Random chance of success if (hasLanded) { resolve('You won a prize!'); // Fulfill the promise } else { reject('Try again!'); // Reject the promise } }); console.log(ringToss); // Logs the Promise object showing its state
Now that you've tossed the ring, you need strategies to handle the outcome, whether a win or a miss.
.then(): This method is used when the promise is fulfilled. It’s like claiming your prize at the carnival booth.
.catch(): This handles rejections or errors. It’s the equivalent of deciding what to do after you miss the ring toss.
.finally(): This method is for code that runs regardless of the outcome, similar to walking away from the booth after winning or losing.
Chaining promises is like playing several carnival games in a row. You must complete one game to receive a token that lets you play the next.
enterBooth() .then(token => playGameOne(token)) .then(prize => tradeForToken(prize)) .then(token => playGameTwo(token)) .then(prize => console.log(`You won: ${prize}`)) .catch(error => console.error('Game error:', error));
In the example of chaining promises above, each step represents a sequential operation, each dependent on the success of the previous one. Here’s what happens in each step:
enterBooth(): This is likely the initial step where you "enter" the asynchronous operation. Imagine it as signing up or logging into an online service. This function returns a Promise.
.then(token => playGameOne(token)): Once you successfully enter, you receive a token. This token is then used to play the first game. This step is also a Promise, dependent on obtaining the token from enterBooth().
.then(prize => tradeForToken(prize)): If you win the first game, you receive a prize. This prize must be traded for another token to continue to the next game. This trading action is another asynchronous operation that returns a Promise.
.then(token => playGameTwo(token)): With the new token, you can play the second game. Again, this step is only possible if the previous step of trading the prize for a token is successful.
.then(prize => console.log(You won: ${prize})): If the second game is won, you will receive another prize. This prize is logged to the console, indicating the successful end of this promise chain.
You might be wondering when the .catch block comes into play. The .catch() block is invoked if any of the Promises in the chain fail or are rejected. This could happen if:
*You failed to enter the booth (enterBooth() fails).
*Any game along the way (playGameOne() or playGameTwo()) does not result in a prize.
*The prize cannot be traded for a token.
In any of these scenarios, the .catch() block catches the error, logs it or takes other corrective action. This prevents the error from stopping the entire script and allows for graceful error handling.
Choosing between Promises and Async/Await largely depends on your project's specific needs. Async/Await might be the clearer choice for complex sequences of dependent operations due to its straightforward syntax and ease of error handling. Conversely, when dealing with multiple, simultaneous operations that do not depend on each other, utilizing Promises with techniques like Promise.all can significantly enhance performance. Both tools are essential in a JavaScript developer’s toolkit, empowering you to write more efficient, cleaner code.
以上が非同期 JavaScript: Promise と Async/Await の詳細の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。