일단 먼저 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로 변환된다.
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 로 받아와 줄 수 있다.
병렬 처리는 여러 작업을 동시에 실행하여 전체 작업을 빠르게 완료하는 것을 의미한다.
비동기 프로그래밍에서는 비동기 작업을 실행하고 완료되는 대로 결과를 수집할 수 있다.
그러나 이런 작업은 단일 스레드에서 실 행 될 수도 있다.
반면, 병렬 처리는 여러 스레드나 프로세스를 사용하여 여러 작업을 동시에 실행한다.
이를 통해 작업을 동시에 처리하고, 여러 개의 코어 또는 프로세서를 활용하여 성능을 향상시킬 수 있다.
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)
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의 호출 결과인 프로미스이다.
이 프로미스들은 각각 동물을 가져오는 비동기 작업을 수행하고 작업이 완료 될 때까지 대기할 수 있는 객체다.