✍️ 참고자료
https://velog.io/@change/JavaScript-asyncawait%EC%97%90-%EB%8C%80%ED%95%B4%EC%84%9C
낯선 promise를 보기 전 동기와 비동기가 어떤건지 알아보자!
동기란 순서대로 하나씩 처리하는 과정을 뜻하며 작업의 실행 순서가 확실히 정해져 있는것을 말한다!
이해가 안된다면 기차를 생각해보자 기차는 정해진 선로를 따라 지나가야하며 기차 한개가 먼저 간 다음 다른 기차가 뒤 따라 가는 방식이다. 이렇듯 동기적 처리는 기차처럼 동작한다 생각하면 된다.
비동기는 먼저 시작한 작업 순서대로가 아닌 처리하고 있는 중간에 또 다른 작업을 시작하는 방식이다.
예를 들면 우리가 공부를 하려다 책상을 정리한 뒤 힘들다고 내일 공부를 다시 시작하는 것과 같다.(이렇듯 나중에 시작한 작업이 먼저 끝나는 경우도 있다. 🤓)
자바스크립트는 콜백 함수, promise, async/await와 같이 비동기 처리 방식이 있다.
만약 한 학생이 고등학교 3학년 교사를 찾는다라고 가정 할 때 다음과 같은 콜백 함수로 찾는다고 가정하자.
//콜백을 여러번 하는것은 콜백 지옥이라 불리며
//직관적이지 못하고 디버깅 할 때 매우 힘들다.
//1. 학교 서버에 학생 학번을 보내는 함수
function 학생정보조회(학번, 학생정보로할일){
ajax(baseUrl + "student-info" + 학번,
function(response){
학생정보로할일(response);
}
);
}
//2. 고교 db 주소 조회
function 고교DB조회(고교명, 주소로할일){
ajax(baseUrl + "highschool-db/" + 고교명,
function(response){
주소로할일(response);
}
);
}
//3. 수강했던 수업과 수업 정보를 받아옴
function 고등학교수업조회(고교DB주소, 학생주민, 수강과목일람){
ajax(baseUrl + "classes/" + 고교DB주소 + "/" + 학생주민,
function(response){
수강과목일람(response);
}
);
}
//4. 교사명 뽑아서 출력
function 수업정보(고3수학수업코드, 수업정보로할일){
ajax( baseUrl + "class-info/" + 고3수학수업코드,
function(response){
수업정보로할일(response);
}
);
}
// --------------------------------
function 고3수학교사찾기(학번){
//신상 받아온 후 뭘 할지 명시하는 콜백함수
학생정보조회(학번, 학생정보로할일
//주민번호, 이름 뽑아내는 함수
function (학생정보){
let 주민번호 = 학생정보['주민번호'];
let 고교명 = 학생정보['고등학교명'];
//2번 함수 시작
고교DB조회(고교명,
//학생정보에서 뽑아낸 주민번호와 db를 불러온다.
function(고교db주소){
//3번 함수 시작
고등학교수업조회(고교db주소, 주민번호,
function(수강과목일람){
let 고3수학수업코드 = 수강과목알람['고3수학'];
//4번 함수 시작
수업정보_조회(고3수학수업코드,
function(수업정보){
console.log(`담당교사: ${수업정보[교사명]}`);
}
)
}
)
}
)
}
)
}
고3수학교사찾기('ㅊ..찾았다?');
(😭적느냐고 죽는줄 알았따...)
이 콜백 지옥을 해결하기 위해 javascript는 es6부터 promise란 걸 도입했다.
📝 promise
Promise 객체는 비동기 작업이 맞이할 미래의 완료 또는 실패와 그 결과 값을 나타냅니다.
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Promise
promise는 다음 중 하나의 상태를 가집니다.
비동기 작업을 사용하는 함수가 promise의 객체를 반환할 때, 생성자 인자로 들어가는 함수에 첫 번째 인자로는 수행할 비동기 작업을 두 번째 인자로는 결과물을 콜백함수에 전달하는 함수가 들어간다.
//학생 정보를 조회하는 함수
function 학생정보조회(학번){
return new Promise(function (resolve, reject){
ajax(baseUrl + "student-info/" + 학번,
function(response){
resolve(response);
});
});
}
// -----------------
function 고교DB조회(학생주민, 고교명){
return new Promise(function (resolve, reject){
ajax(baseUrl + "highschool-db/" + 고교명,
function(response){
resolve([학생주민, response]);
});
});
}
function 고등학교수업조회(고교DB주소, 학생주민){
return new Promise(function (resolve, reject){
ajax(baseUrl + "classes/" + 고교DB주소 + "/" + 학생주민,
function(response){
resolve(response);
});
});
}
function 수업정보(고3수학수업코드){
return new Promise(function (resolve, reject){
ajax(baseUrl + "class-info/" + 고3수학수업코드,
function(response){
resolve(response);
});
});
}
// -------------
학생정보조회('123').then(function(학생정보){
let 학생주민 = 학생정보['주민번호'];
let 고교명 = 학생정보['고등학교명'];
//두 번째 함수
return 고등학교수업조회(학생주민, 고교명)
})
.then(function 주민번호_고교DB주소){
// 세 번째 함수
return 고등학교수업조회(
주민번호_고교DB주소[0],
주민번호_고교DB주소[1]
)
})
.then(function(수강과목알람){
//네 번째 함수
let 고3수학수업코드 = 수강과목알람['고3수학'];
return 수업정보(고3수학수업코드);
})
.then(function(수업정보){
//마지막 담당교사를 찾아주는 함수
console.log(`담당교사: ${수업정보['교사명']}`);
});
//then을 보면 꼬리에 꼬리를 무는 방식이라해서 체이닝 방식이라고 한다.
//이 때 순차적으로 처리하는것을 볼 수 있다.
es7에서 추가 된 기능이며 promise보다 직관적이고 간결하게 사용 할 수 있다!
📝 async
async function 선언은 AsyncFunction객체를 반환하는 하나의 비동기 함수를 정의합니다. 비동기 함수는 이벤트 루프를 통해 비동기적으로 작동하는 함수로, 암시적으로 Promise를 사용하여 결과를 반환합니다.
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Statements/async_function
📝 await
await연산자는 Promise를 기다리기 위해 사용됩니다. 연산자는 async function 내부에서만 사용할 수 있습니다.
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/await
//then으로 꼬리의 꼬리를 무는 방식을 async / await로 짜면 아래와 같다.
async 수학교사찾기(학번){
//학생정보에 promise객체가 들어간다.
let 학생정보 = await 학생정보(학번)
let 고교db주소 = await 고교DB조회(학생정보['고교명']);
let 수광과목알람 = await 고등학교수업조회(학생정보['주민번호'], 고교DB조회);
let 수업정보 = await 수업정보(수강과목알람['고3수학']);
console.log(`담당교사: ${수업정보['교사명']}`);
}
수학교사찾기('123');
async / await를 통해 동기적으로 보이게 작성 할 수 있으며 점점 코드가 직관적으로 보여지는것을 볼 수 있다..
😢 보다보니 코드가 점점 복잡해지는데, 다시 보면서 천천히 복습해야겠다.