상세 컨텐츠

본문 제목

[Javascript] 비동기 처리(3): async/await

😎 지식/FE-리액트🌐

by :Eundms 2021. 8. 17. 23:19

본문

async 함수

: await 키워드는 반드시 async 함수 내부에서 사용해야 한다. async 함수는 async 키워드를 사용해 정의하여 언제나 프로미스를 반환한다. async 함수가 명시적으로 프로미스를 반환하지 않더라도 async함수는 암묵적으로 반환값을 resolve하는 프로미스를 반환한다.

await 

: 프로미스가 settled 상태가 될때까지 대기하다가 settled 상태가 되면 프로미스가 resolve 한 처리결과를 반환한다.


주의해야 한다. 너무 await을 남발하면 느려질 수 있다.

async function foo(){
	const a = await new Promise(resolve=>setTimeout(()=>resolve(1),3000));//settled상태까지3
    const b = await new Promise(resolve=>setTimeout(()=>resolve(2),2000));//2
	const c = await new Promise(resolve=>setTimeout(()=>resolve(3),1000));//1초가 걸려
	console.log([a,b,c])//총 6초가 걸림
}
//하지만, foo함수내 a,b,c는 순차적으로 처리할 필요가 없음

//Promise.all을 사용하자
async function foo(){
	const res = await Promise.all([
        new Promise(resolve=>setTimeout(()=>resolve(1),3000)),
        new Promise(resolve=>setTimeout(()=>resolve(2),2000)),
        new Promise(resolve=>setTimeout(()=>resolve(3),1000)),
    ]);
    console.log(res); //[1,2,3]
}
foo(); //약 3초 소요된다.


//만약, b를 구하는데 a의 결과가 사용된다면 await으로 기다려야 함 nn

async function fetchAndDecode(url, type) {
  let response = await fetch(url);
  let content;
  if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`);
  } else {
    if(type === 'blob') {
      content = await response.blob();
    } else if(type === 'text') {
      content = await response.text();
    }
  }
  return content;
}

async function displayContent() {
  //비동기 함수로 만듦
  let coffee = fetchAndDecode('coffee.jpg', 'blob');
  let tea = fetchAndDecode('tea.jpg', 'blob');
  let description = fetchAndDecode('description.txt', 'text');
  
  //이곳에서 동기로 하기에
  let values = await Promise.all([coffee, tea, description]);

  let objectURL1 = URL.createObjectURL(values[0]);
  let objectURL2 = URL.createObjectURL(values[1]);
  let descText = values[2];

  let image1 = document.createElement('img');
  let image2 = document.createElement('img');
  image1.src = objectURL1;
  image2.src = objectURL2;
  document.body.appendChild(image1);
  document.body.appendChild(image2);

  let para = document.createElement('p');
  para.textContent = descText;
  document.body.appendChild(para);
}

displayContent()
.catch((e) =>
  console.log(e)
);

async/await 주의할 점

async/await 동기식 코드처럼 보이게 한다.

함수 블럭에 여러 개의 await 키워드를 사용하면 Promise가 fulfiled 되기 전까지 다음 await을 차단한다.

그 동안 다른 태스크는 계속 실행이 되지만, 정의한 함수 내에서는 동기적으로 작동한다.

// 내가 이렇게 하고 있다.

 

(1) 비동기로 실행될 Promise가 있다면 async함수 안에 항상 await을 써야한다.

(2) 우리가 작성한 코드가 바로 이어지는 수많은 Promise에 의해 느려질 수 있다.

각 await은 이전의 작업이 끝날 때까지 기다린다.

=> 느려질 수 있다.

해결 방안 =>

// 빠른 비동기 작업으로 바꾸자

모든 Promise 오브젝트를 변수에 저장하여 미리 실행되게하고 

변수가 사용 가능할 때 꺼내서 쓴다.

/*
시작 시간을 기록하고, timeTest() Promise가 fulfilled된 시간을 저장하여 
두 시간의 차를 계산해 작업이 얼마나 걸렸는지 사용자에게 보여줍니다.
*/
   // 느린 비동기 작업
   function timeoutPromise(interval) {
        return new Promise((resolve, reject) => {
          setTimeout(function(){
            resolve("done");
          }, interval);
        });
      };

      async function timeTest() {
        await timeoutPromise(3000);
        await timeoutPromise(3000);
        await timeoutPromise(3000);
      }

      let startTime = Date.now();
      timeTest().then(() => {
        let finishTime = Date.now();
        let timeTaken = finishTime - startTime;
        alert("Time taken in milliseconds: " + timeTaken);
      })
      
      // 빠른 비동기 작업
       function timeoutPromise(interval) {
        return new Promise((resolve, reject) => {
          setTimeout(function(){
            resolve("done");
          }, interval);
        });
      };

      async function timeTest() {
        const timeoutPromise1 = timeoutPromise(3000);
        const timeoutPromise2 = timeoutPromise(3000);
        const timeoutPromise3 = timeoutPromise(3000);

        await timeoutPromise1;
        await timeoutPromise2;
        await timeoutPromise3;
      }

      let startTime = Date.now();
      timeTest().then(() => {
        let finishTime = Date.now();
        let timeTaken = finishTime - startTime;
        alert("Time taken in milliseconds: " + timeTaken);
      })

 

관련글 더보기

댓글 영역