>웹 프론트엔드 >JS 튜토리얼 >비동기 JavaScript: Promise와 Async/Await의 세부사항 비교

비동기 JavaScript: Promise와 Async/Await의 세부사항 비교

WBOY
WBOY원래의
2024-09-03 15:21:29978검색

Asynchronous JavaScript: Promises vs. Async/Await in Details

비동기 프로그래밍은 현대 웹 개발, 특히 JavaScript에서 중추적인 역할을 합니다. 전통적으로 프로그래밍 언어는 코드를 위에서 아래로 순차적으로 실행합니다. 그러나 이 동기 실행 모델은 특히 서버에서 데이터 가져오기, 파일 액세스 또는 복잡한 계산 수행과 같이 시간이 많이 걸리는 작업을 처리할 때 비효율성을 초래할 수 있습니다. 비동기 프로그래밍은 특정 프로세스가 기본 실행 스레드와 독립적으로 실행되도록 하여 웹 애플리케이션의 응답성과 성능을 향상시킴으로써 이러한 문제를 해결합니다.

본질적으로 단일 스레드인 JavaScript는 비동기 프로그래밍을 활용하여 완료될 때까지 실행 스레드를 차단하는 작업을 관리합니다. 이는 본질적으로 완료 시간이 불확실한 작업을 처리하는 데 도움이 되는 콜백, 약속, 비동기/대기 구문과 같은 기능을 통해 달성됩니다. JavaScript에서 비동기 프로그래밍을 마스터하는 것의 중요성은 아무리 강조해도 지나치지 않습니다. 이를 통해 개발자는 더욱 원활하고 빠르며 대화형인 웹 경험을 만들 수 있습니다. 웹사이트와 웹 애플리케이션이 점점 더 복잡해지고 데이터 중심이 되면서 성능을 유지하고 원활한 사용자 경험을 제공하려면 비동기식 작업을 효과적으로 처리하는 것이 중요합니다.

본질적으로 비동기 프로그래밍은 메인 스레드의 차단을 방지하여 웹 애플리케이션의 성능을 최적화할 뿐만 아니라 코드베이스의 확장성과 유지 관리성에 크게 기여합니다. 이 주제를 더 깊이 탐구하면서 JavaScript가 비동기 작업을 처리하기 위해 제공하는 메커니즘과 패턴, 그리고 이것이 현대 웹 개발자의 툴킷에 없어서는 안 될 이유를 살펴보겠습니다.

비동기 자바스크립트 이해

분주한 커피숍의 카운터에서 주문을 한다고 상상해 보세요. 음료가 준비되기를 기다리는 대신, 앉아서 잡지를 살펴보세요. 그 사이 바리스타가 주문을 처리합니다. 커피가 준비되면 바리스타가 커피를 가져오라고 전화합니다. 이 시나리오는 JavaScript에서 비동기 작업이 작동하는 방식과 유사합니다.

JavaScript에서 비동기 작업은 주방에 주문을 보내는 것과 같습니다. 서서 요리사가 끝날 때까지 기다릴 필요가 없습니다. 계속해서 책을 읽거나, 친구와 대화를 나누거나, 카페에서 음악을 즐길 수 있습니다. 주문이 완료되면 알림이 전송되며, 식사를 즐기실 수 있습니다. 마찬가지로 비동기 JavaScript를 사용하면 API 호출이나 파일 작업과 같은 작업을 백그라운드에서 실행할 수 있습니다. 카페에 있는 것처럼 메인 프로그램이 차단되지 않습니다. 계속해서 실행되고 다른 사용자 입력이나 작업에 응답합니다.

JavaScript의 일반적인 비동기 작업

API 호출: 이는 영화를 보면서 배달 서비스에서 음식을 주문하는 것과 같습니다. 음식을 기다리기 위해 영화를 일시 중지하지 않습니다. 계속 지켜보다가 초인종이 울리면 음식이 나옵니다. 웹 개발에서 서버에 데이터를 요청하는 것도 같은 방식으로 작동합니다. 데이터를 요청하고 사이트와 계속 상호 작용하면 데이터가 도착하면 표시됩니다.

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: Promise와 Async/Await의 세부사항 비교의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.