首页  >  文章  >  web前端  >  异步 JavaScript:Promises 与 Async/Await 的详细信息

异步 JavaScript:Promises 与 Async/Await 的详细信息

WBOY
WBOY原创
2024-09-03 15:21:29881浏览

Asynchronous JavaScript: Promises vs. Async/Await in Details

异步编程在现代 Web 开发中至关重要,尤其是 JavaScript。传统上,编程语言从上到下顺序执行代码。然而,这种同步执行模型可能会导致效率低下,尤其是在处理耗时的操作(例如从服务器获取数据、访问文件或执行复杂计算)时。异步编程通过允许某些进程独立于主执行线程运行来解决这些挑战,从而增强 Web 应用程序的响应能力和性能。

本质上是单线程的,JavaScript 利用异步编程来管理操作,否则这些操作会阻塞执行线程直到完成。这是通过回调、promise 和 async/await 语法等功能来实现的,这些功能有助于处理完成时间本质上不确定的操作。掌握 JavaScript 异步编程的重要性怎么强调也不为过。它使开发人员能够创建更流畅、更快速、更具交互性的 Web 体验。随着网站和 Web 应用程序变得越来越复杂和数据驱动,有效处理异步操作对于保持性能和提供无缝用户体验至关重要。

本质上,异步编程不仅通过防止主线程阻塞来优化 Web 应用程序的性能,而且还对代码库的可扩展性和可维护性做出了重大贡献。随着我们深入研究这个主题,我们将探索 JavaScript 提供的用于处理异步操作的机制和模式,以及为什么它们在现代 Web 开发人员的工具包中不可或缺。

了解异步 JavaScript

想象一下在一家熙熙攘攘的咖啡店的柜台下订单。您无需等待饮料准备好,而是坐下来浏览杂志。与此同时,咖啡师正在处理您的订单。咖啡准备好后,咖啡师会打电话给您来取。此场景类似于 JavaScript 中异步操作的工作方式。

在 JavaScript 中,异步操作就像将订单发送到厨房;您不必站着等待厨师完成。您可以继续阅读书籍、与朋友聊天或在咖啡馆欣赏音乐。订单准备好后,您将收到通知,然后您就可以享用餐点了。同样,异步 JavaScript 允许 API 调用或文件操作等任务在后台运行。就像你在咖啡馆一样,主程序不会被阻止;它继续运行并响应其他用户输入或操作。

JavaScript 中常见的异步操作

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!');
});

Promises

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.

Anatomy of a Promise

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.

Creating a Promise Instance

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

Working with Promises

Now that you've tossed the ring, you need strategies to handle the outcome, whether a win or a miss.

Methods to Handle Promises

.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

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.

Final Words

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:Promises 与 Async/Await 的详细信息的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn