Pie_Archive

[React + TypeScript] 비동기 반복문으로 멋지게 처리하기 본문

Front End

[React + TypeScript] 비동기 반복문으로 멋지게 처리하기

코딩파이 2022. 7. 22. 01:46

코드를 짜면서

비동기 처리 함수를 외부로 분리하고

비동기 처리를 반복문으로 처리하고 싶다면 어떻게 해야될까?

 

간단하게 알아보자.

 

1. 비동기 함수 작성

API와 통신하는 여러 비동기 함수가 있겠지만, 이번엔 통신 없이 비동기 처리를 하는 로직을 예시로 들 것이다.

const createThunmbnail = async (file: File) => {

    return new Promise((resolve, reject) => {
      const reader = new FileReader(); // fileReader 인스턴스 생성
      reader.readAsDataURL(file); // 데이터 주입
      reader.onload = () => { //onlaod => 비동기로 처리된다.
        const img = new Image();
        img.src = reader.result as string;
        img.onload = () => { // 이미지 읽는 부분 또한 비동기 처리
          const canvas = document.createElement("canvas"); // 캔버스에 그려서 작은 썸네일 이미지 생성하여
          const ctx = canvas!.getContext("2d");
          ctx!.drawImage(img, 0, 0, 100, 40);
          const dataURI = canvas.toDataURL("image/jpeg");
          resolve(canvas.toDataURL("image/jpeg")) // resolve로 return
      }
    }
  })

 

 

이런 식으로 .onload 메서드는 비동기 형식으로 동작한다.

때문에 이 함수를 먼저 new Promise() 형태로 작성하여 비동기 함수를 만들어줬다.

 

2. 비동기 함수 그냥 사용하기

const fileUpload = async (files: Files) => {
    ...
    const thumbnail = await createThunmbnail(files[0]);
    ...
}

resolve로 return 해 준 값은 이렇게 간단하게 await로 사용할 수 있다.

 

그러나 나는 여러장의 이미지를 업로드 할 때, 순서대로 썸네일을 생성하여 데이터를 저장해주는 로직을 구현하고 싶었고, 결국 비동기 반복문을 사용해야 했다.

 

3. 비동기 반복문 처리, .Map 메서드로 하자.

내가 예전에 비동기 반복문 처리를 못했던 이유가

자주 사용하던 for 문이나 forEach 등 여러 방법으로 처리했었으나 전부 불가능했다.

 

그렇게 이번에도 검색하던 중, 
forEach / filter / reduce 등 메서드에서는 불가능하나,

map 메서드에서는 비동기 처리가 가능하다는 것이다!

 

const thumbPromise = Object.values(files!).map( async file => await createThunmbnail(file));
console.log(thumbPromise) // promise pending
const thumbnails = await Promise.all(thumbPromise);
console.log(thumbnails) // data

1. 우리가 input 으로 읽는 files 형식은 array가 아니라 Object형태이다.
때문에 Object.values() 를 이용하여 array 형태로 변환했다.

 

2. arrya로 변환했으니 map 메서드를 사용하자.

사용법은 간단한데, 꼭 인자 앞에 async를 붙여주자

 

3. 해당 map 을 수행하면 thumbPromise에는 promise array가 담기게 된다. 이를 await Promise.all() 메서드를 이용하여 모든 Promise 객체들이 비동기 처리를 완료할 때 까지 기다려준다.

 

4. 결과를 확인해보자!

 

4. 결론

1. 비동기 반복문 처리를 위해 map 을 사용하자.

2. Promise.all() 메서드로 반복문 배열이 전부 비동기 처리가 완료될 때 까지 기다릴 수 있다. Promise 형태의 비동기 처리에 대해 좀 더 공부가 필요하다.

 

급하게 기능부터 구현하느라 왜 reduce / forEach에서 반복문이 안 되는지 제대로 숙지하지 못했다.

이 참에 Promise부터 다시 공부해야겠다.

 

지적 및 수정은 언제나 환영입니다.