이를 해결하기 위해, '비동기 처리'가 등장하게 된다!
비동기(Asynchronous)는 어떤 일을 수행할 때, 순차적으로 진행하는 것이 아닌 병렬적으로 처리한다.
Blocking을 방지해준다.
- 브라우저에서의 비동기 프로그래밍은 주로 통신과 같이 오래 걸리는 작업들을 브라우저에 위임할 때 이루어진다.
- 서버와의 통신을 할때 받아오는 데이터의 크기가 크고 많을 때 동기적처리를 하면 데이터를 모두 받아오는 시간을 기다린 후에 다음코드를 처리할 것이지만 비동기처리를 이용하면 기다리지 않고 코드 처리가 가능하다.
즉, 비동기는 요청을 보낸 후 응답과 관계없이 다음 동작을 실행할 수 있는 방식을 의미한다.
콜백함수는 특정 함수에 매개변수로 전달된 함수를 의미한다.
그 콜백함수는 함수를 전달받은 함수 안에서 호출된다.
setTimeout함수
- 콜백 지옥 예시
계속 콜백을 호출한다.const f1 = (callback)=>{ setTimeout(function(){ console.log("1번 주문 완료"); callback(); },1000); }; const f2 = (callback)=>{ setTimeout(function(){ console.log('2번 주문 완료'); callback(); },2000); }; const f3 = (callback)=>{ setTimeout(function(){ console.log('3번 주문 완료'); callback(); },3000); }; console.log('시작'); f1(function(){ f2(function(){ f3(function(){ console.log("끝"); }); }); });
콜백 사용의 단점
1. 가독성이 떨어진다.
2. 에러처리를 한다면 모든 콜백에서 각각 에러 핸들링을 해주어야 한다.
promise는 작업이 완료되거나 실행되었을 때 알려준다.
resolve(성공), reject(실패)
new Promise객체가 반환하는 프로미스 개체는 state와 result
처음에는 > state : pending(대기), result : undefined
resolve(value)호출되면(성공시) > state : fulfilled , result:value
reject(error)호출되면(실패시) > satate : rejected , result:error
const pr = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('OK')
},3000)
});
//3초 후에 state:fufilled, result:'OK'
pr.then(
function(result){
console.log(reulst + ' 가지러 가자.');
},//이행되었을때 실행 result:'OK'
function(err){
console.log('다시 주문해주세요..');
}//거부되었을 때 실행
);
//then 이외에 catch사용 가능 단, catch는 에러에만 사용할 수 있다.
//finally는 이행이든 거부든 완료되면 실행됨
pr.then((result)=>{
console.log(result);
})
.catch((err)=>{
console.log(err);
})
.finally(()=>{
console.log('---주문 끝---')
})
- 콜백함수 사용하지 않고 Promise로 구현!
const f1 = () => { return new Promise((res,rej)=>{ setTimeout(()=>{ res('1번 주문 완료'); },1000); }) } const f2 = (message) =>{ console.log(message); return new Promise((res,rej)=>{ setTimeout(()=>{ res('2번 주문 완료'); },3000); }) } const f3 = (message) =>{ console.log(message); return new Promise((res,rej)=>{ setTimeout(()=>{ res('3번 주문 완료'); },2000); }) } //프로미스가 연결연결되는것을 //프로미스 체이닝(Promise chaning)이라고 함 console.log('시작'); f1() .then((res)=>f2(res)) .then((res)=>f3(res)) .then((res)=>console.log(res)) .catch(console.log) .finally(()=>{ console.log('끝'); });
Promise 추가적인 기능
//Promise.all //배열사용
//한번에처리 //시간 절약 가능
//하지만 하나라도 누락되면 아예안보여줌.
//다 보여주거나 다 안보여줄때 사용함
Promise.all([f1(),f2(),f3()])
.then(res =>{
console.log(res);
})
//Promise.race //하나라도 완료되면 끝내버림
Promise.race([f1(),f2(),f3()])
.then(res =>{
console.log(res);
})
Promise로 결과를 반환한다.
async/await를 사용하면 비동기 코드를 마치 동기 코드처럼 보이게 작성할 수 있다.
Promise에 then메소드를 체인형식(프로미스체이닝)으로 호출하는것보다 가속성이 좋다. Promise를 사용하지만 then, catch 메소드를 사용하여 컨트롤 하는 것이 아닌 동기적 코드처럼 반환 값을 변수에 할당하여 작성할 수 있게끔 도와주는 것!
await는 async 내부 함수에서만 사용 가능하다.
Promise를 리턴하는 모든 비동기 함수 호출부 앞에 await를 붙인다.
await를 사용하면 결과값을 얻을 수 있을 때까지 기다려주어 동기적 코드 처리와 동일한 흐름으로 코드를 작성할 수 있다. //함수 호출 후 결과값을 변수에 할당하는 것처럼 작성할 수 있다는 것이다.
동기식 코드에서 쓰는 try...catch 구문을 async/await구조에서 사용할 수 있다.
function getName(name){
return new Promise((res,rej)=>{
setTimeout(()=>{
res(name);
},1000)
})
}
async function showName(){
const res = await getName("Mike");
console.log(res);
}
console.log('시작');
showName();
/*
출력값:
시작
Mike
*/
async~await로 구현
const f1 = () => { return new Promise((res,rej)=>{ setTimeout(()=>{ res('1번 주문 완료'); },1000); }) } const f2 = (message) =>{ console.log(message); return new Promise((res,rej)=>{ setTimeout(()=>{ // res('2번 주문 완료'); rej(new Error("err..")); },3000); }) } const f3 = (message) =>{ console.log(message); return new Promise((res,rej)=>{ setTimeout(()=>{ res('3번 주문 완료'); },2000); }) } console.log("시작"); //reject 에러발생시 try~catch문 이용 async function order(){ try{ const result1 = await f1(); const result2 = await f2(result1); const result3 = await f3(result2); console.log(result3); }catch(e){ //에러처리 console.log(e); } console.log('종료'); } order();