# async, await를 이용한 ajax 통신
async와 await 테스트 코드를 이용하여 비동기로 처리되는 여러개의 ajax를 동기적으로 처리되도록 만들어 보기!
document 와 테스트 코드 블로그.
- async/await: Javascript Info- async/await, test: 보러가기
해당 코드는 올바른 코드라고 생각하진 않음. 따라하지 마셈. 그냥 한번 적용해보고 싶어서 하는 거임.
# 환경
/**
* tool: STS 4.13.0
* version: 2.7.3-SNAPSHOT
* java: 1.8
* type: MAVEN
* view: THYMELEAF
* jQuery: 3.6.0
*/
# 페이지
# HTML
<h1>동기/비동기 테스트 페이지 입니다.</h1>
<div>
<input id="toggle" type="button" onclick="toggle()" value="START" style="display: inline;"/>
<br>
<h3>SYNC/ASYNC</h3>
<input type="button" onclick="callType(false)" value="SYNC" style="display: inline;"/>
<input type="button" onclick="callType(true)" value="ASYNC" style="display: inline;"/>
<br>
<input type="button" onclick="callType(true, 'THEN')" value="ASYNC THEN" style="display: inline;"/>
<input type="button" onclick="callType(false, 'THEN')" value="SYNC THEN" style="display: inline;"/>
<br>
<input type="button" onclick="callType(true, 'AWAIT')" value="ASYNC AWAIT" style="display: inline;"/>
<input type="button" onclick="callType(false, 'AWAIT')" value="SYNC AWAIT" style="display: inline;"/>
<br>
<input type="button" onclick="callType(true, 'ALL')" value="ASYNC THEN ALL" style="display: inline;"/>
<input type="button" onclick="callType(false, 'ALL')" value="SYNC THEN ALL" style="display: inline;"/>
<br>
<input type="button" onclick="callTest()" value="TEST CALL" style="display: inline;"/>
</div>
# ajax 호출 함수, sleep ajax 함수.
// ajax test 호출 함수.
function callType(isAsync, name) {
const type = (isAsync) ? '비동기' : '동기';
console.log(`${name}: START(${type}):`, timestamp());
if(name === 'THEN') {
callThen(isAsync);
} else if(name === 'ALL') {
callThenAll(isAsync);
} else if(name === 'AWAIT') {
callAwait(isAsync);
} else {
call(isAsync);
}
console.log(`${name}: STOP(${type}):`, timestamp());
}
// 실제 ajax 함수.
function promiseSleep(isAsync, ss) {
return new Promise(function(resolve) {
const type = (isAsync) ? '비동기' : '동기';
console.log(`${ss}SS: CALL(${type}):`, timestamp());
$.ajax(`/test/async/sleep${ss}`,
{
// settings
method : "GET",
async : isAsync,
data : {
text: 'sleep on!'
},
dataType: "json",
}).done(function(output, textStatus, jqXHR) {
console.log(`${ss}SS: BACK(${type}):`, timestamp());
}).fail(function(jqXHR) {
}).always(function(output, textStatus, jqXH) {
console.log(`${ss}SS: COMPLETE(${type}):`, timestamp());
resolve('ajax is complete!');
}
);
});
}
# Controller
@Slf4j
@Controller
@RequestMapping("/test/async")
public class TestAsyncController {
@GetMapping("/sleep2")
public ModelAndView sleep2(@RequestParam Map<String, String> input) {
// 2초 대기.
TestAsyncController.delay(2000);
ModelAndView mav = new ModelAndView("jsonView");
mav.addObject("output", "sleep2 Ok!");
return mav;
}
@GetMapping("/sleep3")
public ModelAndView sleep3(@RequestParam Map<String, String> input) {
// 3초 대기.
TestAsyncController.delay(3000);
ModelAndView mav = new ModelAndView("jsonView");
mav.addObject("output", "sleep2 Ok!");
return mav;
}
@GetMapping("/sleep4")
public ModelAndView sleep(@RequestParam Map<String, String> input) {
// 4초 대기.
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
ModelAndView mav = new ModelAndView("jsonView");
mav.addObject("output", "sleep4 Ok!");
return mav;
}
@GetMapping("/test")
public ModelAndView test(@RequestParam Map<String, String> input) {
ModelAndView mav = new ModelAndView("jsonView");
mav.addObject("output", "test Ok!");
return mav;
}
// 어쩌다가 발견한 delay 함수
public static boolean delay(int ms) {
long now = System.currentTimeMillis();
long after = now + ms;
while(after >= now) {
now = System.currentTimeMillis();
}
return true;
}
}
# 테스트 코드에서 TYPE1 과 같은...
async function callAwait(isAsync) {
const message4 = await promiseSleep(isAsync, 4);
console.log(timestamp(), ':', message4);
const message2 = await promiseSleep(isAsync, 2);
console.log(timestamp(), ':', message2);
}
/* ASYNC
ING: 17:28:41
ING: 17:28:42
AWAIT: START(비동기): 17:28:42
4SS: CALL(비동기): 17:28:42
AWAIT: STOP(비동기): 17:28:42
ING: 17:28:43
ING: 17:28:44
ING: 17:28:45
ING: 17:28:46
4SS: BACK(비동기): 17:28:46
4SS: COMPLETE(비동기): 17:28:46
17:28:46 : ajax is complete!
2SS: CALL(비동기): 17:28:46
ING: 17:28:47
ING: 17:28:48
2SS: BACK(비동기): 17:28:48
2SS: COMPLETE(비동기): 17:28:48
17:28:48 : ajax is complete!
ING: 17:28:49
ING: 17:28:50
*/
- 이전 블로그에서 작성한 테스트 코드에서 TYPE1 과 같은 진행을 구현하고 싶었다.
- 함수는 비동기로 해당 함수호출 후 종료. (비동기로 진행중이라 스크립트는 계속 진행)
- 4초 함수 종료 후, 2초 함수 실행.
# TYPE1 내용
- 지연되는 시간이 있지만, 스크립트가 비동기적으로 움직이면서, 동기적으로 실행된다는 점에서 메리트가 있다.
- 순서가 보장되어야 하는 연속 비동기 ajax에 적합 할 듯 하다.
# TYPE1 대신
- 첫번째 ajax가 끝나고 done이나 complete 함수에서 또 다른 ajax를 실행해도 됨.(트리 모양으로 ajax가 진행됨.)
# 테스트 코드에서 TYPE2, TYPE3과 같은...
function callTest() {
const isAsync = true;
Promise.all([promiseSleep(isAsync, 4), promiseSleep(isAsync, 2), promiseSleep(isAsync, 3)]).then((messages) => {
if(messages[0] && messages[1] && messages[2]) {
console.log('3개의 ajax 완료!');
}
callTestAjax();
});
}
function callTestAjax() {
$.ajax(`/test/async/test`,
{
// settings
method : "GET",
async : true,
data : {text: 'sleep on!'},
dataType: "json",
}).done(function(output, textStatus, jqXHR) {
console.log("OUTPUT:", output);
}).fail(function(jqXHR) {
}).always(function(output, textStatus, jqXH) {
});
}
/*
ING: 21:34:55
ING: 21:34:56
4SS: CALL(비동기): 21:34:56
2SS: CALL(비동기): 21:34:56
3SS: CALL(비동기): 21:34:56
ING: 21:34:57
ING: 21:34:58
2SS: BACK(비동기): 21:34:58
2SS: COMPLETE(비동기): 21:34:58
ING: 21:34:59
3SS: BACK(비동기): 21:34:59
3SS: COMPLETE(비동기): 21:34:59
ING: 21:35:00
4SS: BACK(비동기): 21:35:00
4SS: COMPLETE(비동기): 21:35:00
3개의 ajax 완료!
OUTPUT: {output: 'test Ok!'}
ING: 21:35:01
ING: 21:35:02
*/
- 여러개의 ajax 가 동시에 비동기로 처리되고, 함수는 종료된다.
- ajax가 다르게 끝나더라고 마지막에 종료되는 ajax를 await 해준다.
- 다 종료가 되면 실제로 실행되어야 하는 ajax(callTestAjax)를 실행.
- 앞에 2초지연, 3초지연, 4초지연 ajax는 callTestAjax를 실행하기 위한 사전 작업 같은 느낌의 통신으로 볼수있다!
- 앞선 ajax가 완료 된 후, 최종 ajax의 실행이 보장되는 프로세스에 적합 할 듯 하다.
# TYPE2, TYPE3 내용
- 예를 들어 3개의 ajax는 고객정보를 가져오고, 특정 DB의 데이터를 가져오고, 고객이 입력한 내용을 업데이트를 한 뒤에 시퀀스를 가져옴.
- 3개의 데이터를 조합한 데이터를 "DB에 적재" 또는 "특정 제휴사에게 전달" 해야 된다면,
- 비동기로 동시에 진행 시킨 이후에 await 한 후 진행하면 조금 더 빠른 프로세스를 만들수 있지 않을까 싶음!
- 간편하게 하려면 해당 데이터를 동기적으로 구현해야 하며, 4+3+2=9초로 한번하는데 9초를 기다려야한다.
- 그 와중에 동기여서 다른 스크립트는 멈춘 상태!
# TYPE2, TYPE3 대신,,,,
let is2Done = false;
let is3Done = false;
let is4Done = false;
function isDone() {
if(is2Done && is3Done && is4Done) {
// 실행되어야 하는 ajax....
}
}
- 각각의 함수종료를 나타내는 변수를 만들어주고, done()에서 true로 변경 후, isDone() 실행해도 됨.
# 내용
async/await을 다루고 싶었고, ajax에 적용해서 사용해보고 싶었다.
# JavaScript 시리즈
https://hjho95.tistory.com/21 async, await
https://hjho95.tistory.com/22 async, await를 이용한 ajax
# JavaScript 시리즈의 참조 페이지
async/await: https://ko.javascript.info/async-await
'자바스크립트' 카테고리의 다른 글
[JavaScript] html dom 성능개선 관련 async defer 적용하기! (2) | 2022.09.10 |
---|---|
[JavaScript] async, await 테스트 (2) | 2022.09.10 |
[Vanilla JS] fetch - POST, application/json 로 요청하기! (0) | 2022.09.04 |
[Vanilla JS] fetch - POST, application/x-www-form-urlencoded 로 요청하기! (0) | 2022.09.04 |
[Vanilla JS] fetch - GET, application/x-www-form-urlencoded 로 요청하기! (0) | 2022.09.04 |