본문 바로가기
Front-end/JavaScript

비동기 처리(Promise 객체)

by bloodFinger 2019. 12. 18.

저번시간에 배웠던 콜백 함수!

권장하지 않는 방법이다.

 

요새 많은 사람들이 사용하는 Promise 에 대해서 공부해 보자!

 

 

왜 Promise가 필요한가?

ajax가 서버에다 데이터 하나만 주세요 라는 요청을 보낸다. 그런데 데이터를 받아오기도 전에 마치 데이터를 

다 받아온 것 처럼 화면에 데이터를 표시하려고 하면 오류가 발생하거나 빈 화면이 뜬다.

이러한 문제점을 해결하기 위한 방법중 하나가 프로미스이다!!

 

간단한 예를 통해서 설명을 해보겠습니다.

 

function getData(callbackFunc) {
  $.get('url 주소/products/1', function (response) {
    callbackFunc(response); // 서버에서 받은 데이터 response를 callbackFunc() 함수에 넘겨줌
  });
}

getData(function (tableData) {
  console.log(tableData); // $.get()의 response 값이 tableData에 전달됨
});

위의 코드는 콜백함수를 이용한 jquery ajax 통신이다. 위의 코드를 프로미스를 적용해 보겠다.

 

function getData(callback) {
  return new Promise(function (resolve, reject) {
    $.get('url 주소', function (response) {
      resolve(response); // 데이터를 받으면 resolve() 호출
    });
  });
}

// getData()의 실행이 끝나면 호출되는 then()
getData().then(function (tableData) {
  // resolve()의 결과 값이 여기로 전달됨
  console.log(tableData); // $.get()의 reponse 값이 tableData에 전달됨
});

 

프로미스 상태(state)는 생성하고 종료될 때까지 3가지 상태를 갖습니다.

 

1. pending(대기) : 비동기 처리 로직이 아직 완료 되지 않은 상태  

2. Fulfilled (이행/완료 ) : 비동기 처리가 완료 되어 프로 미스가 결과 값을 반환해준 상태

3. Rejected (실패) : 비동기 처리가 실패 OR 오류가 발생한 상태

 

1. new Priomise() 메소드를 호출하면 대기 상태가 됩니다.

2.resolve()를 실행하면 이행/완료 상대가 되고 then()을 이용해서 처리 결과값을 받을 수 있습니다.

3.new Promise() 객체 생성을 하면 콜백 함수 인자로 resolve와 reject를 사용 할 수 있다고 했습니다.

여기서 reject 인자로 reject 메소드를 실행하면 Rejected(실패) 상태가 됩니다.

 

프로미스 처리 흐름 - 출처 : MDN

 

 

 

개념은 정리 되었고 그럼 내 프로젝트 코드를 Promise기법을 사용해서 refactoring 해보자

 

 

$(document).on("click", "#regist", function(){
	if($('#content').val() == ''){
			var toastTop = app.toast.create({
	            text: '댓글을 입력하세요.',
	            position: 'top',
	            closeButton: true,
	          });
	          toastTop.open();
              
	}else{
    	promise_func().then(saveAlarmAjax).catch(function(err){
				console.log(err);
		});
    }

});

간략히 설명하면 댓글 달기 버튼을 클릭했을때 내용이 유무에 따라 유효성 검사를 한다!

 

function promise_func(){
		return new Promise(function(resolve, reject){
			$.ajax({
				type : 'post',
				url : '/mentor/menteeboardReply/menteeboardReplyWrite',
				data : $('#menteeboardViewForm').serialize(),
				dataType : 'json',
				success : function(data){
					if(data){
						$('#inputList').empty();
						$('#content').val('');
						$('.count').text(data.list.length);

						let $frag = $(document.createDocumentFragment());
						menteeboardViewList(data);
						$('#inputList').append('<div class="block mentee-detail-block thanks-note-card" id="menteeboardPagingDiv">'+data.menteeboardPaging.pagingHTML+'</div><hr>');
						
						resolve();
					}else{
						reject('fail');
					}
				}
			});
		});
	}

여기서 봐야할부분은 data가 잘왔다면 resolve() , 데이터가 없다면 reject()를 호출한다

	let memNickname = $('#memNickname').val();
	let nickname = $('#nickname').val();
	let receiverEmail = $('#email').val();
	let menteeboard_seq = $('#menteeboard_seq').val();
	
	var AlarmData = {
			"myAlarm_receiverEmail" : receiverEmail,
			"myAlarm_callerNickname" : memNickname,
			"myAlarm_title" : "댓글 알림",
			"myAlarm_content" :  memNickname + "님이 <a type='external' href='/mentor/menteeboard/menteeboardView?seq="+menteeboard_seq+"&pg=1'>" + menteeboard_seq + "</a> 번 게시글에 댓글을 남겼습니다."
	};

	//댓글작성에 대한 알림 저장
	function saveAlarmAjax(){
		return new $.ajax({
						type : 'post',
						url : '/mentor/member/saveAlarm',
						data : JSON.stringify(AlarmData),
						contentType: "application/json; charset=utf-8",
						dataType : 'text',
						success : function(data){
							//socket에 보내자
							alert(JSON.stringify(AlarmData));
							if(socket) {
								let socketMsg = "reply," + memNickname +","+ nickname +","+ receiverEmail +","+ menteeboard_seq;
								console.log("msgmsg : " + socketMsg);
								socket.send(socketMsg);
							}
						}
					});
	}

여기에서는 댓글이 작성이 된후에 웹소켓으로 전달하는 ajax이다

 

 

 

결론

ajax가 꼬리에 꼬리를 물고 생기지 않아서 가독성이 좋아진 부분을 알 수 있다.

 

 

'Front-end > JavaScript' 카테고리의 다른 글

비동기 처리(Callback hell)  (0) 2019.12.17