웹사이트 검색

JavaScript에서 Async/Await 함수 탐색


소개

Promise는 코드의 비동기성을 순차적으로 처리하는 더 쉬운 방법을 제공합니다. 우리의 두뇌가 비동기성을 효율적으로 처리하도록 설계되지 않았다는 점을 고려하면 이것은 매우 반가운 추가 사항입니다. ES2017(ES8)에 새로 추가된 Async/await 함수는 백그라운드에서 비동기 작업을 수행하면서 완전히 동기식으로 보이는 코드를 작성할 수 있도록 도와줍니다.

비동기 함수를 사용하여 달성한 기능은 약속을 생성기와 결합하여 다시 만들 수 있지만 비동기 함수는 추가 상용구 코드 없이 필요한 것을 제공합니다.

간단한 예

다음 예제에서는 먼저 2초 후에 🤡 값으로 확인되는 약속을 반환하는 함수를 선언합니다. 그런 다음 async 함수를 선언하고 메시지를 콘솔에 기록하기 전에 해결될 약속을 await합니다.

function scaryClown() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve('🤡');
    }, 2000);
  });
}

async function msg() {
  const msg = await scaryClown();
  console.log('Message:', msg);
}

msg(); // Message: 🤡 <-- after 2 seconds

await는 약속이 해결되거나 거부되기를 기다리는 데 사용되는 새로운 연산자입니다. 비동기 함수 내에서만 사용할 수 있습니다.

비동기 함수의 힘은 여러 단계가 관련되어 있을 때 더욱 분명해집니다.

function who() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve('🤡');
    }, 200);
  });
}

function what() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve('lurks');
    }, 300);
  });
}

function where() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve('in the shadows');
    }, 500);
  });
}

async function msg() {
  const a = await who();
  const b = await what();
  const c = await where();

  console.log(`${ a } ${ b } ${ c }`);
}

msg(); // 🤡 lurks in the shadows <-- after 1 second

그러나 주의할 점은 위의 예에서 각 단계는 순차적으로 수행되며 각 추가 단계는 계속하기 전에 해결하거나 거부하기 전에 단계를 기다립니다. 대신 단계를 병렬로 수행하려면 Promise.all을 사용하여 모든 약속이 이행될 때까지 기다리면 됩니다.

// ...

async function msg() {
  const [a, b, c] = await Promise.all([who(), what(), where()]);

  console.log(`${ a } ${ b } ${ c }`);
}

msg(); // 🤡 lurks in the shadows <-- after 500ms

Promise.all은 전달된 약속이 모두 해결되면 해결된 값이 있는 배열을 반환합니다.

위의 코드에서 우리는 코드를 간결하게 만들기 위해 멋진 배열 구조 분해를 사용합니다.

약속-반환

비동기 함수는 항상 약속을 반환하므로 다음은 원하는 결과를 생성하지 못할 수 있습니다.

async function hello() {
  return 'Hello Alligator!';
}

const b = hello();

console.log(b); // [object Promise] { ... }

반환되는 것은 약속이므로 대신 다음과 같이 할 수 있습니다.

async function hello() {
  return 'Hello Alligator!';
}

const b = hello();

b.then(x => console.log(x)); // Hello Alligator!

...또는 이것만:

async function hello() {
  return 'Hello Alligator!';
}

hello().then(x => console.log(x)); // Hello Alligator!

다른 형태

지금까지 예제에서 비동기 함수를 함수 선언으로 보았지만 비동기 함수 표현식과 비동기 화살표 함수도 정의할 수 있습니다.

비동기 함수 표현식

다음은 첫 번째 예제의 비동기 함수이지만 함수 표현식으로 정의됩니다.

const msg = async function() {
  const msg = await scaryClown();
  console.log('Message:', msg);
}

비동기화살표 함수

동일한 예가 다시 한 번 있지만 이번에는 화살표 함수로 정의됩니다.

const msg = async () => {
  const msg = await scaryClown();
  console.log('Message:', msg);
}

오류 처리

비동기 함수의 또 다른 좋은 점은 오류 처리가 오래된 try…catch 문을 사용하여 완전히 동기식으로 수행된다는 것입니다. 시간의 절반을 거부하는 약속을 사용하여 시연해 봅시다.

function yayOrNay() {
  return new Promise((resolve, reject) => {
    const val = Math.round(Math.random() * 1); // 0 or 1, at random

    val ? resolve('Lucky!!') : reject('Nope 😠');
  });
}

async function msg() {
  try {
    const msg = await yayOrNay();
    console.log(msg);
  } catch(err) {
    console.log(err);
  }
}

msg(); // Lucky!!
msg(); // Lucky!!
msg(); // Lucky!!
msg(); // Nope 😠
msg(); // Lucky!!
msg(); // Nope 😠
msg(); // Nope 😠
msg(); // Nope 😠
msg(); // Nope 😠
msg(); // Lucky!!

비동기 함수가 항상 약속을 반환한다는 점을 감안할 때 일반적으로 catch 문을 사용하는 것처럼 처리되지 않은 오류를 처리할 수도 있습니다.

async function msg() {
  const msg = await yayOrNay();
  console.log(msg);
}

msg().catch(x => console.log(x));

이 동기식 오류 처리는 약속이 거부된 경우뿐만 아니라 실제 런타임 또는 구문 오류가 발생한 경우에도 작동합니다. 다음 예에서는 msg 함수를 호출하여 두 번째로 toUpperCase 메서드가 없는 number 값을 전달합니다. 프로토타입 체인. try…catch 블록도 해당 오류를 포착합니다.

function caserUpper(val) {
  return new Promise((resolve, reject) => {
    resolve(val.toUpperCase());
  });
}

async function msg(x) {
  try {
    const msg = await caserUpper(x);
    console.log(msg);
  } catch(err) {
    console.log('Ohh no:', err.message);
  }
}

msg('Hello'); // HELLO
msg(34); // Ohh no: val.toUpperCase is not a function

Promise 기반 APIS를 사용한 비동기 함수

Fetch API 입문서에서 살펴본 것처럼 약속 기반 웹 API는 비동기 함수를 위한 완벽한 후보입니다.

async function fetchUsers(endpoint) {
  const res = await fetch(endpoint);
  let data = await res.json();

  data = data.map(user => user.username);

  console.log(data);
}

fetchUsers('https://jsonplaceholder.typicode.com/users');
// ["Bret", "Antonette", "Samantha", "Karianne", "Kamren", "Leopoldo_Corkery", "Elwyn.Skiles", "Maxime_Nienow", "Delphine", "Moriah.Stanton"]

브라우저 지원:

결론

Async/await 함수 이전에는 많은 비동기 이벤트에 의존하는 JavaScript 코드(예: API를 많이 호출하는 코드) 일부에서 \콜백 지옥\이라고 하는 상황에 처했습니다. 읽고 이해하기 매우 어려웠던 함수 및 콜백.

Async 및 await를 사용하면 훨씬 더 명확하게 읽는 비동기 JavaScript 코드를 작성할 수 있습니다.