ajax 부가기능

jinkyung·2021년 2월 4일
0

Ajax

목록 보기
6/8
  • 전처리 후처리가 가능하다
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script>
// 성공 : BeforeSend -> success -> complete
// 실패 : BeforeSend -> error -> complete 
	function reqList(){
		$.ajax({
			url : "/Contact/list.do",
			type : "GET",
			data : {pageno:5, pagesize:5},
			beforeSend : function(xhr, settings){
				console.log("Before Send");
			},
			success : function(data){
				console.log("success");
				$("#resp").html(data);
			},
			error : function(xhr, status, error){
				console.log("error : " + status + ", " + error);
			},
			complete : function(xhr, status){
				console.log("complete");
			}
		});
	}
	function delList(){
		$("#resp").html("");
	}
</script>
</head>
<body>
	<button type="button" onclick="reqList();">요청</button>
	<button type="button" onclick="delList();">삭제</button>
	<p id="resp"></p>
</body>
</html>


  • 없는 url 주소로 변경시 error


  • 시간이 지체될 때 timeout 속성을 통해 처리할 수 있다.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script>
	// list_long.do는 2초 후에 응답처리
	// timeout은 1.9초면 더 기다리지 않고 timeout처리
	function reqList(){
		$.ajax({
			url : "/Contact/list_long.do",
			type : "GET",
			timeout : 1900,
			data : {pageno:5, pagesize:5},
			beforeSend : function(xhr, settings){
				console.log("Before Send");
			},
			success : function(data){
				console.log("success");
				$("#resp").html(data);
			},
			error : function(xhr, status, error){
				console.log("error : " + status + ", " + error);
			},
			complete : function(xhr, status){
				console.log("complete");
			}
		});
	}
	function delList(){
		$("#resp").html("");
	}
</script>
</head>
<body>
	<button type="button" onclick="reqList();">요청</button>
	<button type="button" onclick="delList();">삭제</button>
	<p id="resp"></p>
</body>
</html>


  • ajax라는 함수를 대신해서 get/post 함수를 쓸 수도 있다.
    좀 더 쉽게(간단하게) 요청하고 싶다면 쓸 수 있다.

get_post.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script>
	/*
	$.ajax() 함수를 대신해서 사용할 수 있는 단축 함수
	1) $.get() : GET 요청
	2) $.post() : POST 요청
	*/
	function reqList0(){
		$.get("/Contact/list.do", function(data){
			$("#resp").html(data);
		});
	}
	function reqList1(){
		var param = {};
		param.name = "트와이스";
		param.tel = "010-0000-2222";
		param.address = "충남";
		
		$.post("/Contact/add.do", param, function(data){
			$("#resp").html(data);
		});
	}
	function reqList2(){
		$.get({
			url : "/Contact/list_long.do",
			data : {pageno:2, pagesize:5},
			timeout : 1900,
			success : function(data){
				$("#resp").html(data);
			},
			error : function(xhr, status, error){
				$("#resp").html(status + ", " + error);
			}
		});
	}
	function delList(){
		$("#resp").html("");
	}
</script>
</head>
<body>
	<button type="button" onclick="reqList0();">get 요청-0</button>
	<button type="button" onclick="reqList1();">post 요청-1</button>
	<button type="button" onclick="reqList2();">get 요청-2</button>
	<button type="button" onclick="delList();">삭제</button>
	<p id="resp"></p>
</body>
</html>

get요청-2 결과


  • jqXHR = jquery 기능 + xhr 객체

jqXHR.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script>
	function reqList(){
		var jqXHR = $.ajax({
			url : "/Contact/list_long.do",
			type : "GET",
			data : {pageno:2, pagesize:5}
		});
		// success
		jqXHR.done(function(data, status, xhr){
			console.log("done");
			console.log(data);
		});
		// error
		jqXHR.fail(function(data, status, eror){
			console.log("fail");
			console.log(status + ", " + error);
		});
		// complete
		jqXHR.always(function(){
			console.log("always");
		});
	}
	function delList(){
		$("#resp").html("");
	}
</script>
</head>
<body>
	<button type="button" onclick="reqList();">요청</button>
	<button type="button" onclick="delList();">삭제</button>
	<p id="resp"></p>
</body>
</html>

  • timeout을 줄 경우 error




  • 가끔은 동기식이 필요할 때

ajaxGET_Sync.html
: 좋은 방법은 아니다.

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script>
/*
 * 아래처럼 순서대로 요청하는 방법은 응답이 올때까지
   계속 $.ajax()함수가 대기하게 되므로 
   결국 reqList()함수도 계속 리턴하지 못하고 대기에 들어간다.
  그런데 이 상황에서 사용자의 이벤트가 발생하면 main thread는
  $.ajax()에 의해 대기되므로 화면이 정지하거나
  불안정한 상태가 되어 브라우저가 꺼지기도 한다.
  
  그래서 deprecated라고 표시된다.
 */*/
	function reqList(){
		console.log("1 page 요청");
		$.ajax({
			url:"/Contact/list_long.do",
			type:"GET",
			async:false,			// 동기
			data:{pageno:1, pagesize:5},
			success:function(data){
				console.log("1 page 응답");
				console.log(data);
				$("#resp").html(data);
			}
		});
		
		console.log("2 page 요청");
		$.ajax({
			url:"/Contact/list.do",
			type:"GET",
			async:false,			// 동기
			data:{pageno:2, pagesize:5},
			success:function(data){
				console.log("2 page 응답");
				console.log(data);
				$("#resp").html(data);
			}
		});
		
		console.log("3 page 요청");
		$.ajax({
			url:"/Contact/list.do",
			type:"GET",
			async:false,			// 동기
			data:{pageno:3, pagesize:5},
			success:function(data){
				console.log("3 page 응답");
				console.log(data);
				$("#resp").html(data);
			}
		});
	}
	function delList(){
		$("#resp").html("");
	}
	function sleep(ms) {
		  return new Promise(resolve=>setTimeout(resolve, ms));
	}
</script>
</head>
<body>
	<button type="button" onclick="reqList();">요청</button>
	<button type="button" onclick="delList();">삭제</button>
	<p id="resp"></p>
</body>
</html>

callbackHell.html
콜백 동기
: 너무 많아지면 안좋다.

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script>
	// 아래처럼 순서를 동기화하면 
	// 보내야 하는 요청이 많을 때
	// 콜백안에서 계속 다시 요청해야 하므로 코드의 가독성이 매우 떨어지게 된다.
	function reqList(){
		console.log("Send Page1");
		$.get("/Contact/list_long.do", {pageno:1}, function(data){
			console.log("page1 success : " + (new Date()).toLocaleTimeString());
			console.log(data);
			
			console.log("Send Page2");
			$.get("/Contact/list_long.do", {pageno:2}, function(data){
				console.log("page2 success : " + (new Date()).toLocaleTimeString());
				console.log(data);
				
				console.log("Send Page3");
				$.get("/Contact/list_long.do", {pageno:3}, function(data){
					console.log("page3 success : " + (new Date()).toLocaleTimeString());
					console.log(data);
				});
			});
		});
	}
	function delList(){
		$("#resp").html("");
	}
</script>
</head>
<body>
	<button type="button" onclick="reqList();">요청</button>
	<button type="button" onclick="delList();">삭제</button>
	<p id="resp"></p>
</body>
</html>

callbackAsync.html
콜백 비동기
: 일단 요청이 응답과 상관없이 모두 실행이 되므로 빨리 끝나는 것을 먼저 응답해주기 때문에 순서대로 실행완료 할 수가 없다.

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script>

	function reqList(){
		console.log("Send Page1");
		$.get("/Contact/list_long.do", {pageno:1}, function(data){
			console.log("page1 success : " + (new Date()).toLocaleTimeString());
			console.log(data);
		});		
		
		console.log("Send Page2");
		$.get("/Contact/list_long.do", {pageno:2}, function(data){
			console.log("page2 success : " + (new Date()).toLocaleTimeString());
			console.log(data);
		});
		
		console.log("Send Page3");
		$.get("/Contact/list_long.do", {pageno:3}, function(data){
			console.log("page3 success : " + (new Date()).toLocaleTimeString());
			console.log(data);
		});
	}
	function delList(){
		$("#resp").html("");
	}
</script>
</head>
<body>
	<button type="button" onclick="reqList();">요청</button>
	<button type="button" onclick="delList();">삭제</button>
	<p id="resp"></p>
</body>
</html>


그렇다면 어떻게 동기식으로 처리해야 할까?
아래와 같은 방법을 쓸 수 있다.

callback_jqXHR_then.html
: get이 끝나는 시점에 jqxhr객체를 통해서 호출이 끝나는 순간 then(function)을 실행 -> 리턴객체가 끝나는 시점에 다시 then으로 다시 함수 호출

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script>
  // then은 $get() 함수가 호출된 jqXHR.then이고, 이것은 해당 요청이 완료된 후라는 뜻이다
  // 순서대로 호출되는 것을 확인할 수 있다.
	function reqList(){
		$.get("/Contact/list_long.do", {pageno:1}).then(function(data){
			console.log("promise page 1 : " + (new Date()).toLocaleTimeString());
			console.log(data);
			return $.get("/Contact/list_long.do", {pageno:2});
		}).then(function(data){
			console.log("promise page 2 : " + (new Date()).toLocaleTimeString());
			console.log(data);
			return $.get("/Contact/list_long.do", {pageno:3});			
		}).then(function(data){
			console.log("promise page 3 : " + (new Date()).toLocaleTimeString());
			console.log(data);			
		})
	}
	function delList(){
		$("#resp").html("");
	}
</script>
</head>
<body>
	<button type="button" onclick="reqList();">요청</button>
	<button type="button" onclick="delList();">삭제</button>
	<p id="resp"></p>
</body>
</html>



  • 여러개의 요청이 모두 끝났을 때 호출되도록

jqXHR_Multi.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script>

	function reqList(){
		//default가 3 이므로 0은 3개 / 1은 5개
		var jqXHR0 = $.get("/Contact/list_long.do", {pageno:1});
		var jqXHR1 = $.get("/Contact/list.do", {pageno:3, pagesize:5});
		
		// 2개의 요청이 모두 완료되었을 때 호출
        	/* data0, data1 => type은 Array Object
		   data0[0], data[0] => type은 string
		   string을 js객체로 변환 => JSON.parse()
		*/
		$.when(jqXHR0, jqXHR1).done(function(data0, data1){
			console.log(data0);
			console.log(data1);
			var obj0 = JSON.parse(data0[0]);
			var obj1 = JSON.parse(data1[0]);
			//contacts라는 필드에 접근해서 갯수를 얻어낸 것이다.
			var totalCount = obj0.contacts.length + 
							obj1.contacts.length;
			console.log("2번의 요청으로 조회된 데이터 건수의 합 : " + totalCount);
		});
	}
	function delList(){
		$("#resp").html("");
	}
</script>
</head>
<body>
	<button type="button" onclick="reqList();">요청</button>
	<button type="button" onclick="delList();">삭제</button>
	<p id="resp"></p>
</body>
</html>




helper_function.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script>
	$(document).ready(function(){
		$("#save").click(function(){
			var name = $("#name").val();
			var gender = $("input.gender:checked").val();
			var age = $("#age > option:selected").val();
			
			var param = "name=" + encodeURIComponent(name);
			param += "&gender=" + gender + "&age=" + age;
			console.log(param);
		});
	});
</script>
</head>
<body>
	<form id="f1">
		이름 : <input type="text" id="name" name="name"/><br/>
		성별 : 
		  남 <input type="radio" class="gender" name="gender" value="M" checked/><input type="radio" class="gender" name="gender" value="F" /><br/>
		연령대 :
		  <select id="age" name="age">
		  	<option value="" selected>--연령대를 선택하세요</option>
		  	<option value="10">~19</option>
		  	<option value="10">20~29</option>
		  	<option value="10">30~39</option>
		  	<option value="10">40~49</option>
		  	<option value="10">50~59</option>
		  	<option value="10">60~</option>
		  </select>
	</form>
	<button id="save">저장</button>
</body>
</html>


helper 함수 이용시 form에 있는 데이터들을 쉽게 만들 수 있다.

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script>
	/*
		helper 함수
		1) $(form).serialize()
		   ; 인코딩된 폼데이터로 생성(application/x-www-form-urlencoded 형식)
		2) $(form).serializeArray()
		   ; 객체 배열 생성
		3) $.param()
		   ; 객체/객체 배열을 인자로 받으면 인코딩된 폼데이터 생성
		4) JSON.stringify(obj)
		   ; js 객체 -> json 문자열
		5) JSON.parse(str)
		   ; json 문자열 -> js 객체
	*/
	$(document).ready(function(){
		$("#save").click(function(){
			// 1) application/x-www-form-urlencoded 형식으로 만드는 코드
            		// (form의 action)
			// serialize시 일일이 뽑지 않아도 자동으로 만들어준다 (post에 보내는 형태로 만들어준다 )
			// serialize array -> 배열로 만들어준다 
			var param = $("#f1").serialize();
			console.log(param);
			
			// 2) json 문자열로 만들고 싶다
			var paramJson = $("#f1").serializeArray();
		    console.log(paramJson);
		    console.log(JSON.stringify(paramJson));
		    
		    // 3) 객체/객체 배열 -> 인코딩 폼 데이터
		    console.log($.param(paramJson));
		});
	});
</script>
</head>
<body>
	<form id="f1">
		이름 : <input type="text" id="name" name="name"/><br/>
		성별 : 
		  남 <input type="radio" class="gender" name="gender" value="M" checked/><input type="radio" class="gender" name="gender" value="F" /><br/>
		연령대 :
		  <select id="age" name="age">
		  	<option value="" selected>--연령대를 선택하세요</option>
		  	<option value="10">~19</option>
		  	<option value="10">20~29</option>
		  	<option value="10">30~39</option>
		  	<option value="10">40~49</option>
		  	<option value="10">50~59</option>
		  	<option value="10">60~</option>
		  </select>
	</form>
	<button id="save">저장</button>
</body>
</html>



ajax_global_event.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script>
	/* 어떤 ajax 통신이 진행되던
	   document에서 발생하는 모든 ajax의 이벤트를 감지하는 callback 함수 등록
	   전역 ajax 이벤트
	*/
	$(document).ready(function(){
		$(document).ajaxStart(function(){
			console.log("AJAX START !!");
		}).ajaxStop(function(){
			console.log("AJAX STOP !!");
		}).ajaxSend(function(e, xhr, options){
			console.log("AJAX SEND !!" + options.url);
		}).ajaxSuccess(function(e, xhr, options, data){
			console.log("AJAX SUCCESS !!" + options.url);
		}).ajaxComplete(function(e, xhr, options){
			console.log("AJAX COMPLETE !!" + options.url);
		});
	});
	function reqList(){
		$.get({
			url : "/Contact/list.do",
			beforeSend : function(){
				console.log("1-beforeSend : list.do");
			},
			success : function(){
				console.log("1-success : list.do");
			},
			complete : function(){
				console.log("1-complete : list.do");
			}
		});
		$.get({
			url : "/Contact/list_long.do",
			beforeSend : function(){
				console.log("2-beforeSend : list_long.do");
			},
			success : function(){
				console.log("2-success : list_long.do");
			},
			complete : function(){
				console.log("2-complete : list_long.do");
			}
		});
	}
	function delList(){
		$("#resp").html("");
	}
</script>
</head>
<body>
	<button type="button" onclick="reqList();">요청</button>
	<button type="button" onclick="delList();">삭제</button>
	<p id="resp"></p>
</body>
</html>

전역이벤트 감지 후 로컬이벤트 감지 (시작과 보내는 것)
success, complete는 로컬이 먼저 감지되는 것을 확인 가능
전역이벤트 : 통신이 시작되고 일괄적으로 처리해줘야할 것이 있을 때 전역이벤트를 쓸 수 있다.


  • 일괄처리가 필요한경우 - setup으로 묶어서 처리 가능
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script>
	$(document).ready(function(){
		$(document).ajaxStop(function(){
			console.log("AJAX STOP !!");
		});
		
		// 모든 ajax에 timeout 1.9초가 적용이 된다
		// 여기에 설정하는 것이 default설정으로 적용된다
		$.ajaxSetup({
			timeout : 1900,
           	//	 global : false, 전역이벤트 발생 x 
			error : function(jqXHR, status, error){
				console.log("error : " + error);
			}
		});
	});
	function reqList(){
		// 따로 timeout을 설정하지 않았으므로 위의 1.9초 적용 
		// 2초이므로 error 
		$.get("/Contact/list_long.do", function(data){
			console.log(data);
		});
	}
	function delList(){
		$("#resp").html("");
	}
</script>
</head>
<body>
	<button type="button" onclick="reqList();">요청</button>
	<button type="button" onclick="delList();">삭제</button>
	<p id="resp"></p>
</body>
</html>


global : false를 줬을 경우



ajaxPrefilter.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script>

// 비동기 전송이기 때문에 버튼을 여러번 누를 수 있다(요청 버튼)
// 그럼 get요청이 응답하고 리턴해버려서 reqList가 종료된다 
// 그런데 여기서는 전송 중일때는 버튼을 눌러도 재요청이 발생하지 않도록 하기 위해 작성한 것이다.
// 즉 기존 전송이 완료되기 전에 재전송 막기 
	$(document).ready(function(){
		// 현재 전송중인지를 체크하기 위해 만든 객체 
		var currentRequests = {}; //js 객체 생성 
		
		// ajax 통신 직전에 처리하는 일 
		$.ajaxPrefilter(function(options, originalOptions, jqXHR){
			// abortOnRetry가 true면 
			if(options.abortOnRetry){
				// url이 존재하냐 -> 처음엔 존재x (false) 빈 객체니까! 
				//한번 더 누르면 객체가 존재하므로 객체가 들어있으므로 true 
				if(currentRequests[options.url]){
					jqXHR.abort();
					console.log("abort Request");
				}else {
					// 빈 객체일 때 등록 
					currentRequests[options.url] = jqXHR;
				}
			}
		});

	
	// 기존 전송이 완료되기 전에 재전송 막기 
	$(document).ajaxComplete(function(e, jqxhr, options){
		if(options.abortOnRetry){
			delete currentRequests[options.url];
		}
	});
});
	var count = 0;
	function reqList(){
		$.get({
			url : "/Contact/list_long.do",
			// 통신이 이루어지기 전에 항상 filter가 호출된다 
			abortOnRetry : true,
			beforeSend : function(xhr, settings){
				count++;
				console.log("send " + count + " Request");
			},
			success : function(data){
				console.log("success " + count + " Request !!");
				console.log(data);
			},
			error : function(xhr, status, error){
				console.log("error " + count + " Request");
			}
		});
	}
	function delList(){
		$("#resp").html("");
	}
</script>
</head>
<body>
	<button type="button" onclick="reqList();">요청</button>
	<button type="button" onclick="delList();">삭제</button>
	<p id="resp"></p>
</body>
</html>

abort가 뜨는 것을 확인할 수 있다.

0개의 댓글

관련 채용 정보