[JavaScript] 비동기 패턴: 직렬과 병렬처리 및 안티패턴

박용희·2023년 8월 25일
0

[JavaScript] 비동기 패턴: 직렬과 병렬처리 및 안티패턴

전체 코드

      async function fetchDataAsync(id) {
        return new Promise((resolve, reject) => {
          setTimeout(() => {
            const data = { id, name: "John" + id };
            if (data) {
              resolve(data);
            } else {
              reject("Data not found");
            }
          }, Math.random()*1000); 
        });
      }

      async function fetchDataSerially() {
        const dataArray = [];

        for (let i = 1; i <= 5; i++) {
          try {
            const data = await fetchDataAsync(i);
            dataArray.push(data);
            console.log("Data:", data);
          } catch (error) {
            console.error("Error:", error);
          }
        }
        console.log("Data Array:", dataArray);
      }

      fetchDataSerially();


      async function fetchDataParallel() {
        try {
          const promises = [];
          for (let i = 1; i <= 5; i++) {
            promises.push(fetchDataAsync(i));
          }
          const dataArray = await Promise.all(promises);
          console.log("Data Array:", dataArray);
        } catch (error) {
          console.error("Error:", error);
        }
      }

      fetchDataParallel();

      async function fetchDataForEach() {
        const dataArray = [];

        [1, 2, 3, 4, 5].forEach(async (i) => {
          try {
            const data = await fetchDataAsync(i);
            dataArray.push(data);
            console.log("Data:", data);
          } catch (error) {
            console.error("Error:", error);
          }
        });

        console.log("Data Array:", dataArray);
      }

      fetchDataForEach();

비동기 함수

 async function fetchDataAsync(id) {
 	return new Promise((resolve, reject) => {
 		setTimeout(() => {
            const data = { id, name: "John" + id };
            if (data) {
              resolve(data);
            } else {
              reject("Data not found");
            }
        }, Math.random()*1000); 
	});
}

무작위 시간이 지나고 data를 반환하도록 하는 비동기 함수입니다.

직렬처리 코드

async function fetchDataSerially() {
	const dataArray = [];

	for (let i = 1; i <= 5; i++) {
    	try {
        	const data = await fetchDataAsync(i);
            dataArray.push(data);
            console.log("Data:", data);
          } catch (error) {
            console.error("Error:", error);
          }
     }
     console.log("Data Array:", dataArray);
}

fetchDataSerially(); 
// 출력결과
// Data: {id: 1, name: 'John1'}
// Data: {id: 2, name: 'John2'}
// Data: {id: 3, name: 'John3'}
// Data: {id: 4, name: 'John4'}
// Data: {id: 5, name: 'John5'}
// Data Array: (5) [{…}, {…}, {…}, {…}, {…}]

직렬처리는 비동기 작업을 순차적으로 처리합니다.

이전의 작업이 완료가 되어야 다음 작업을 시작하는 방식입니다.

직렬 처리 장점

  • 순서 보장
  • 의존성 처리
  • 안정성

직렬 처리 단점

  • 성능 저하
  • 병목 현상

병렬처리 코드

async function fetchDataParallel() {
	try {
		const promises = [];
        for (let i = 1; i <= 5; i++) {
        	promises.push(fetchDataAsync(i));
        }
        const dataArray = await Promise.all(promises);
        console.log("Data Array:", dataArray);
        } catch (error) {
          console.error("Error:", error);
        }
}

fetchDataParallel();
// 출력결과: Data Array: (5) [{…}, {…}, {…}, {…}, {…}]

Promise.all은 내부적으로 비동기 작업을 병렬로 처리하고 결과를 모아서 반환합니다.

이 비동기 작업은 싱글 스레드에서 병렬적으로 처리되는 것은 아니지만, 비동기 특성을 활용하여 효과적인 병렬 작업 처리를 구현한 것입니다.

병렬처리 장점

  • 성능 향상
  • 자원활용
  • 응답성 향상
  • 대기시간 감소

병렬처리 단점

  • 동기화와 동시성 관리
  • 코드 복잡성
  • 데이터 일관성
  • 병렬화 비용

forEach 안티패턴

async function fetchDataForEach() {
	const dataArray = [];

	[1, 2, 3, 4, 5].forEach(async (i) => {
		try {
            const data = await fetchDataAsync(i);
            dataArray.push(data);
            console.log("Data:", data);
          } catch (error) {
            console.error("Error:", error);
          }
	});

	console.log("Data Array:", dataArray);
}

fetchDataForEach();
// 출력결과
// Data Array: []
// Data: {id: 2, name: 'John2'}
// Data: {id: 5, name: 'John5'}
// Data: {id: 1, name: 'John1'}
// Data: {id: 4, name: 'John4'}
// Data: {id: 3, name: 'John3'}

위의 코드는 비동기 콜백 함수가 async로 선언되어 있어도, forEach 안에서는 각 비동기 작업이 병렬로 실행되지 않습니다.

그렇기 때문에 console.log부터 먼저 실행을 하게 되고, data를 가져오는 과정은 비동기 처리하게 됩니다.

forEach 안에 있는 내부의 함수가 완료되지 않는 상태에서 console.log를 하게 되면, 데이터를 가지고 오는 각 시간에 따라서 순서가 보장이 되지 않는 문제점이 있을 수 있습니다.

0개의 댓글