[TS 과제 챌린지] Exchange Rate Calculator - 트러블슈팅

조민호·2023년 5월 29일
0

이번주는 비동기 관련한 사항을 많이 다룹니다


비동기 처리 유의 할 점

  1. .json()에도 await을 써야 합니다

    const getData = async () => {
      const data = await fetch('https://open.exchangerate-api.com/v6/latest');
      let result = await data.json(); **// await한번 더 써야 함**
    
      console.log(result.rates); // {USD: 1, AED: 3.6725, AFN: 86.041136, ALL: 103.215184, AMD: 390.57593, …}
      return result.rates;
    };
    
    console.log(getData()); // Promise {<pending>} (fulfilled)

    axios는 상관이 없지만 fetch로 데이터를 가져올 경우 , json()으로 변환을 한번 해줘야 합니다

    이 때 역시, 해당 데이터가 동기적으로 받아져 왔을때 진행돼야 하므로 await을 사용해야 합니다

    만약 then()을 사용했을땐 아래와 같이 진행합니다

    const data = await fetch('https://open.exchangerate-api.com/v6/latest')
        .then((res) => res.json())
    		.then((res) => res.rates);
    
    return data;

  1. pending 처리하기

    const getData = async () => {
      const data = await fetch('https://open.exchangerate-api.com/v6/latest');
      let result = await data.json(); **// await한번 더 써야 함**
    
      console.log(result.rates); // {USD: 1, AED: 3.6725, AFN: 86.041136, ALL: 103.215184, AMD: 390.57593, …}
      return result.rates;
    };
    
    console.log(getData()); // Promise {<pending>} (fulfilled)

    첫번째 콘솔창에는 제대로 뜨지만 외부에서 출력할 경우

    pending이 발생합니다

    당연히 비동기로 처리되는 로직을 전역에서 먼저 불러버리기 때문 입니다

    이럴 해결하려면 2가지 방법이 있습니다

    • then으로 해결
      const getData = async () => {
        const data = await fetch('https://open.exchangerate-api.com/v6/latest');
        let result = await data.json(); // await한번 더 써야 함
      
        console.log(result.rates); // {USD: 1, AED: 3.6725, AFN: 86.041136, ALL: 103.215184, AMD: 390.57593, …}
        return result.rates;
      };
      
      getData().then(res=>{
        console.log(res) // {USD: 1, AED: 3.6725, AFN: 86.041136, ALL: 103.215184, AMD: 390.57593, …}
      })
      .then을 사용해서 처리하면 됩니다


    • await으로 해결 다만, then을 사용하는 것 보다 async/await을 사용하는걸 더 선호한다면 async 함수에서 사용하면 됩니다
      const getData = async () => {
        const data = await fetch('https://open.exchangerate-api.com/v6/latest');
        let result = await data.json(); // await한번 더 써야 함
      
        console.log(result.rates); // {USD: 1, AED: 3.6725, AFN: 86.041136, ALL: 103.215184, AMD: 390.57593, …}
        return result.rates;
      };
      
      const printData = async () => {
        const rates = await getData();
        console.log(rates); // {USD: 1, AED: 3.6725, AFN: 86.041136, ALL: 103.215184, AMD: 390.57593, …}
      };
      사실 실제 JS로직을 작성할 때 기능들을 함수 단위로 끊어서 사용하며 , 전역에서 비동기처리 결과값을 받는 일은 거의 없기 때문에 함수를 추가적으로 사용한다고 해도 전혀 문제가 없습니다

3. 비동기 코드의 동기적인 동작을 보장하기

“ 위처럼 fetch를 사용해서 정보를 가져오는 데이터가 있고, 이걸 사용하려는 모든 함수에 전부 다 async/await 을 사용해야 하나? “

그렇습니다.
이렇게 함으로써 비동기 코드의 동기적인 동작을 보장하는 것입니다

const getData = async () => {
  const data = await fetch('https://open.exchangerate-api.com/v6/latest');
  let result = await data.json(); // await한번 더 써야 함
  return result.rates;
};

**// 비동기로 받은 값을 사용해야 하므로 await을 사용**
const getRate1 = async (): Promise<object> => {
  const currency = await getData();
  return currency;
};

**// 비동기로 받은 값을 사용해야 하므로 await을 사용**
const getRate2 = async (): Promise<void> => {
  const rate: object = await getRate1();
};

getRate2();

지금은 단순해 보일지 몰라도

비동기 데이터를 가져오는 a함수가 있을 때

  • b함수가 a함수가 가져온 데이터값을 호출하고
  • c함수가 b함수가 받은 데이터값을 호출하고
  • d함수가 c함수가 받은 데이터값을 호출할 때

a,b,c,d 모두 다 await을 사용해야 합니다




프로미스 타입

TS에서 비동기 처리를 진행하는 함수가 있으면

반드시 프로미스 타입으로 묶어서 명시해 줘야 합니다

Promise<number>  // number를 반환하는 프로미스 타입
Promise<string>  // string을 반환하는 프로미스 타입
Promise<number[]> // number[]를 반환하는 프로미스 타입
Promise<T> // 제네릭을 반환하는 프로미스 타입

void를 리턴하는 것은 생략이 가능했지만, 프로미스의 경우 반드시 Promise로 리턴 타입을 명시해줘야 합니다

// Promise를 사용하여 비동기 작업을 처리하는 함수
async function processData(url: string): **Promise<void>** {

  try {
    // fetchData 함수가 완료될 때까지 기다립니다.
    const data = await fetchData(url);

    // 비동기 작업이 완료되면 결과를 처리합니다.
    console.log('Data:', data);
  } catch (error) {
    // 에러가 발생하면 처리합니다.
    console.error('Error:', error);
  }
}
profile
할 수 있다

0개의 댓글