[Javscript] promise로 콜백지옥 탈출하기
콜백지옥
내가 짠 코드가 바로 콜백지옥인가 보다🤣🤣
$(document).ready(function () {
console.log("기존 멤버 수 : " + existingMemberNum);
// ajax로 목록 불러오기
searchAjax("");
<c:forEach var="i" items="${partyList}">
addExistingMembers(${i.emp_code}, "${i.empname}");
disableCheckbox(${i.emp_code}) // 체크박스를 수정할 수 없도록 상태를 disabled로 수정
</c:forEach>
});
searchAjax()
-> addExistingMembers(code, name)
-> disableCheckbox(code)
순으로 실행하고 싶었는데, 순서가 꼬여서 뒤에 두 함수가 제대로 실행되지 않았다.
Promise로 콜백함수 실행하기
사전등록을 해놓으면, 사이트가 오픈된 후에 자동으로 초대이메일이 발송되는 프로그램이 있다고 가정해보자. 철수는 사이트 오픈 전에 사전등록을 해두어서, 오픈 후 초대메일을 받게 되었다. 영희는 사이트가 이미 오픈된 후에야 사전등록을 했는데, 이미 사이트가 오픈된 후이기 때문에 기다리지 않고 바로 메일을 받을 수 있었다.
Promise는 비동기를 수행할 때 콜백함수 대신 유용하게 쓸 수 있는 javascript에 내장된 object이다. 두가지의 핵심개념을 이해하면 편하다.
- State
- pending : Promise가 만들어져서 우리가 지정한 operzation이 수행중일 때
- fullfilled : operation이 완료된 상태
- rejected: operation이 거부된 상태
- Producer vs Consumer
- Producer는 원하는 기능을 수행하고 해당하는 데이터를 만든다.
- 정상적으로 수행 시 resolve를 반환한다.
- 오류가 발생하는 경우에는 reject를 반환하고, 에러가 발생하는 이유를 적어두는 것이 좋다.
- Consumer는
then
,catch
,finally
로 값을 처리한다.- then : Promise가 정상적으로 수행했을 경우 resolve 콜백함수를 통해 값을 전달받는다.
- catch : Promise가 에러 발생 시 reject 콜백함수를 통해 값을 전달받는다.
- finally : 결과와 상관없이 마지막에 무조건 실행된다.
- Producer는 원하는 기능을 수행하고 해당하는 데이터를 만든다.
-
Producer
- 새로운 프로미스가 만들어질 때, 전달한 executor라는 콜백함수가 바로 실행된다.
-
따라서 내부에 불필요한 network 통신이 발생하지는 않는지 유의할 필요가 있다.
- resolve와 reject를 인자로 받는다.
const promise = new Promise((resolve, reject) =>{ // doing some heavy work (network, read files) console.log('doing somethingk...'); setTimeout(() => { resolve('ellie'); // reject(new Error('no network')); },2000); });
-
Consumers
promise .then((value) => { // 성공했을 때 실행 // value는 resolve에서 전달된 'ellie'라는 값이 들어온다. console.log(value); }).catch(error => { // 실패했을 때 실행 console.log(error); }).finally(() => { // 성공여부와 상관없이 마지막에 실행 console.log('finally'); })
-
Promise chaining
const fetchNumber = new Promise((resolve, reject) => { // 서버통신에서는 setTimeout을 자주 쓴다. setTimeout(() => resolve(1), 1000); }) fetchNumber .then(num => num*2) .then(num => num*3) .then(num => { return new Promise((resolve, reject) => { setTimeout(() => resolve(num - 1), 1000); }) }) // then은 값을 바로 전달할 수도 있고, promise를 전달할 수도 있다.
참고(1) - 매개변수를 하나만 전달하는 경우
매개변수를 하나만 전달하는 경우 생략해도 알아서 매개변수를 전달한다.
// 생략 전
getHen()
.then(hen => getEgg(hen))
.then(cook => cook(egg))
.then(meal => console.log(meal));
// 생략 후
getHen()
.then(getEgg)
.then(cook)
.then(console.log)
참고(2) - 용국쓰 코드
function fn_getSearchEmpList(code){
return new Promise(function (resolve,reject) {
var tid= setTimeout(function () {
$.ajax({
type : "POST",
url : "/test/getSearchEmpList",
data :{code:code},
dataType :"json",
success : function(data) {
// 수행하는 긴코드 생략
$("#empWrapper"+data.team_code).append(html);
resolve(data);
$(".allcontainer").attr("class","allcontainer w-100");
}
});
},100)
});
}
fn_getDeptList().then(fn_getteamlist).then(fn_getemplist);
댓글남기기