[ Javascript ] - async 와 await / 병렬처리

슬로그·2023년 7월 6일
0

JS

목록 보기
6/7
post-thumbnail

1. Promise 대신 aync 키워드

일단 먼저 Promise 가 있는 코드를 한번보자

	1-1)
   
	function fetchUser(){
		return new Promise((resolve,reject) =>{
			resolve('bosule');
		})
	}
	const user = fetchUser();
	user.then(console.log);
	console.log(user);

1-1) 이렇게 Promise를 이용하지 않고 더 간편하게 쓸수 있는게 async 문법이다.

	1-2)
    
  	aync function fetchUser(){ // 함수앞에 aync 작성
      return 'bosule'
	}
	const user = fetchUser();
	user.then(console.log);
	console.log(user);

1-2)
함수 앞에 aync 를 작성해주면 자동적으로 Promise로 변환된다.

2. await

await 키워드는 aync가 붙은 키워드 안에서만 쓸수있다.

	2-1)
    
    function delay(ms) {
      return new Promise(resolve => setTimeout(resolve,ms));
    }	

    async function getDog(){
      await delay(3000);
      return '강아지';
    }

    async function getCat(){
      await delay(1000);
      return '고양이';
    }

2-1)
delay라는 함수는 Promise를 리턴하는데 정해진 millisecond가 지나면 resolve가 호출하는 Promise를 리턴하게된다.

await가 붙은 키워드는 async함수 안에서만 작성할 수 있는데 getDog와 getCat 함수에서 await를 작성하고 delay 함수를 불러온 뒤 인자로 millisecond를 전달해주면 전해준 millisecond 만큼 기다려준 뒤 '강아지' 와 '고양이'를 호출해주는 함수이다.
await를 붙여줌으로써 delay가 끝날때까지 기다려 주게 된다.

만약 위에 코드를 Promise를 쓰는 함수로 만들어보자면

  2-2)
  
  function getDog(){
      return delay(3000)
      .then(() => '강아지')
    }

2-2)와 같이 체이닝을 하는 것 보다
2-1)처럼 동기적으로 코드를 작성하는 것처럼 작성하면 좀 더 쉽게 직관?적으로 코드를 이해할 수 있다.

만약 getDog와 getCat을 둘다 데려오고 싶을때에는 어떻게 해야할까 ?

 2-3)

 function getAnimal(){
   return getDog()
   .then(dog => {
     return getCat()
       .then(cat => `${dog} + ${cat}`)
   })
 }
 getAnimal().then(console.log);

 2-4)
 
 async function getAnimal(){
   const dog = await getDog();
   const cat = await getCat();
   return `${dog} + ${cat}`
 }

 getAnimal().then(console.log);

2-3 코드를 보면 콜백지옥에 빠지게 될수있는 위험성이 있다.
2-4) 코드처럼 async 와 await 키워드를 이용해 동기적인 코드를 작성하듯이 간편하게 작성해 줄 수 있다.

만약 에러처리를 해야한다면

   2-4)
   
   async function getCat(){
    await delay(1000);
    throw 'error' // 에러를 던저주고
    return '고양이';
  }

	async function getAnimal(){
    	try{  // 성공시 
        	  const dog = await getDog();
      		  const cat = await getCat();
        }catch(error){ // 에러 시엔 catch를 이용해
        	console.error // 에러반환
        }
      return `${dog} + ${cat}`
    }
	

2-4) getCat 함수에 에러를 던져주고 성공시엔 try / 에러가 났을경우 catch 로 받아와 줄 수 있다.

3. async / await 병렬처리

병렬 처리는 여러 작업을 동시에 실행하여 전체 작업을 빠르게 완료하는 것을 의미한다.
비동기 프로그래밍에서는 비동기 작업을 실행하고 완료되는 대로 결과를 수집할 수 있다.
그러나 이런 작업은 단일 스레드에서 실 행 될 수도 있다.
반면, 병렬 처리는 여러 스레드나 프로세스를 사용하여 여러 작업을 동시에 실행한다.
이를 통해 작업을 동시에 처리하고, 여러 개의 코어 또는 프로세서를 활용하여 성능을 향상시킬 수 있다.

3-1. Promise.all 으로 비동기 작업 병렬 처리 하기

  • Promise.all 함수는 여러개의 프로미스를 인자로 받아 하나의 프로미스를 반환하는 함수인데, 전달된 모든 프라미스가 완료될 때 까지 기다리며 그 결과로 프로미스들의 결과를 배열로 반환한다.
    이러한 동작들 때문에 Promise.all을 사용하면 비동기 작업을 병렬로 실행 할 수 있다.

  • Promise.all 함수는 내부적으로 각 프로미스를 동시에 실행하고, 모든 프로미스가 완료될때까지 대기한다.
    이때 각 프로미스의 완료 순서는 상관없이 결과를 반환하는 순서는 프로미스가 전달된 순서를 따른다.

  • 예를 들어 Promise.all([promise1, promise2, promise3]) 와 같이 세 개의 프로미스를 전달하면 각 프로미스는 병렬로 실행된다. 프로미스가 병렬로 실행되므로 전체 작업이 완료되는데 걸리는 시간은 가장 오래걸리는 작업의 시간에 의해 결정된다.
    따라서 , 모든 작업이 병렬로 처리되면서 전체 작업 시간을 단축 시킬 수 있다.

  • 이러한 특성 때문에 Promise.all은 비동기 작업을 병렬로 처리하는데에 매우 유용하다.
    여러개의 비동기 작업을 동시에 실행하고 모든 작업이 완료될 때까지 대기하면서 작업의 결과를 한번에 받아올 수 있다.
    이는 성능과 응답성을 향상시키는데 도움을 준다.

	3-1)
	async function fetchData(url) {
      // 비동기 작업을 수행하는 함수
      // 예를 들어 HTTP 요청을 보내 데이터를 가져오는 등의 작업을 수행한다고 가정
      // 이 함수는 Promise를 반환
      const response = await fetch(url); 
      return response.json(); 
    }

    async function parallelProcessing() {
      try {
        const url1 = 'https://api.example.com/data1';
        const url2 = 'https://api.example.com/data2';

        // 여러 개의 비동기 작업을 병렬로 실행
        const [data1, data2] = await Promise.all([fetchData(url1), fetchData(url2)]);

        // 작업이 완료되면 각각의 결과에 접근할 수 있다.
        console.log('Data 1:', data1);
        console.log('Data 2:', data2);
      } catch (error) {
        console.error('Error:', error);
      }
    }

    parallelProcessing();

3-1) 에서 fetchData 함수는 비동기 작업을 수행하는 함수 이다. fetch를 이용해 HTTP요청을 보내고 응답을 JSON형식으로 파싱하여 반환한다.

parallelProcessing 함수에서는 Promise.all을 사용해 fetchData 함수를 병렬로 실행할 수 있다..
이때 fetchData에 url1 과 url2를 배열로 전달한다.
Promise.all 은 전달된 모든 프로미스가 완료 될때 까지 기다리며 모든 작업이 완료되면 각 작업의 결과를 배열로 반환한다.

await Promise.all([fetchData(url1),fetchData(url2)]) 구문에서 'await'를 사용하여 'Promise.all'의 결과를 대기하고 해당 결과를 [data1, data2] 와같은 배열로 할당한다. 이후 각각의 결과에 접근하여 원하는 작업을 수행할 수 있다.

이렇게 하면 fetchData(url1)fetchData(url2)가 동시에 실행이 되며 두작업이 완료되어야만 다음 단계로 진행된다.

3-2. aync await 에서 비동기 작업 병렬 처리 실행하기

	3-2)
    
	async function pickAnimal(){
      const dogPromise = getDog();
      const catPromise = getCat();
      const dog = await dogPromise;
      const cat = await catPromise;

      return `${dog} + ${cat}`
    }

3-2) 코드는 dogPromise 와 catPromise 는 getdog함수와 getCat를 호출해 반환된 프로미스를 할당한다.
이때 두 비동기 작업은 병렬로 실행된다.
즉, getDog와 getCat함수는 동시에 호출 되어 동물들을 가져오는 작업이 시작된다.
await 키워드를 사용해 dogPromise 와 catPromise 의 완료를 기다린다.
await는 프로미스가 이행될 때 까지 현재 함수의 실행을 일시 중단한다. 따라서 dogPromise 와 catPromise 의 완료를 기다린 후 각각의 결과를 dog 와 cat 변수에 할당한다.

이 코드는 getDog와 getCat의 함수를 병렬로 실행해 동물을 가져온 후 가져온 동물들을 결합하는 방식으로 비동기 처리를 수행한다.
await 키워드를 사용해 비동기 작업의 완료를 기다리기 때문에 작업은 순차적으로 진행된다.
즉 getDog의 작업 완료를 기다린 후 getCat 함수를 호출한다.

dogPromise 와 catPromise는 비동기 함수인 getDog 와 getCat의 호출 결과인 프로미스이다.
이 프로미스들은 각각 동물을 가져오는 비동기 작업을 수행하고 작업이 완료 될 때까지 대기할 수 있는 객체다.

profile
빨리가는 유일한 방법은 제대로 가는것

0개의 댓글