JQuery를 이용한 ajax 처리 시 보통 비동기로 처리하지만 동기 처리를 통해 결과값을 받아야하는 경우가 있다. 이때 ajax 옵션에 async:false 를 넣어주면 동기방식으로 처리를 할 수 있기에 자주 사용을 했었는데 특정 기기 환경에서 결과값을 받지 못하는 경우가 발생했다.
처음엔 AJAX 처리시 오류가 발생했나 하여 디버깅을 여러번 해보았지만 AJAX 결과는 정상적으로 처리되었고 실제 최종 결과값만 undefined 가 되었다. 해당 소스는 대충 아래와 같은 구조로 되어있다.
function ajax(req){
var ret = {};
$.ajax(req)
.done(function(e){ret =e;});
return ret;
}
$(function(){
var ret = ajax({url:'/shop/pay',dataType:'json',async:false});
alert(ret.rst);
});
분명 대부분의 기기 환경에서는 잘 작동되는데 유독 특정 기기에서만 결과값을 받지 못하고 alert 실행 시 undefined가 출력되었다. 하지만 이상하게도 ajax로 전송된 백단에서는 정상적으로 처리가 되고 있었다. 마치 비동기로 전송한것과 같은 결과였다.
지금까지 JQuery로 막코딩은 했지만 이런 경우는 처음이라 아래와 같이 여러 방법을 동원해서 시도해보았다.
| 실패
function ajax(req){
var ret = {};
$.ajax(req)
.done(function(e){ret =e;});
return ret;
}
$(function(){
var ret = ajax({url:'/shop/pay',dataType:'json',async:false});
setTimeout(function(){
alert(ret.rst);
},500);
});
setTimeout 으로 0.5초의 딜레이를 두고 처리해 봤는데 결과는 역시나 실패였다. 당연하게도 이방식은 setTimeout 과 무관하게 실행된 ajax 내부 함수에서 결과값을 못당겨 올 수 밖에 없다. 그래서 아래와 같이 ajax 함수를 추가로 수정하여 결과값을 그냥 받아보았다.
| 잘못된 방법
function ajax(req){
return $.ajax(req);
}
$(function(){
var ret = ajax({url:'/shop/pay',dataType:'json',async:false});
setTimeout(function(e){
alert(JSON.parse(ret.responseText).rst);
},500);
});
결과값을 받긴했는데 기존 함수를 수정하면 안되는 상황이기에 다시 되돌려 놓았다. 또한 위의 방법은 통신 환경이나 프로그램 처리에 시간이 소요되기라도 하면 이건 그냥 무용지물인 결과물이고 차라리 비동기로 바꾸고 객체를 그대로 받아서 done에서 결과값을 받고 처리하는게 맞다.
만약 비동기로 변경해서 done으로 결과값을 받는다면 아래와 같이 할 수 있다.
function ajax(req){
return $.ajax(req);
}
$(function(){
var ret = ajax({url:'/shop/pay',dataType:'json'});
ret.done(function(e){
alert(e.rst);
});
});
지금까지 ajax 동기 처리시 결과값을 못받는 경우는 처음 겪어보는 일이라 난감했다. 예제 소스들은 당시 상황을 보여주기 위해 간단하게 만든 소스이고 실제 사용된 소스는 복잡한 처리 후 ajax를 통해 공통 결과를 처리한 후 최종 결과를 return 하는 함수였다.
결과적으로 ajax 에서 async:false 로 동기 처리를 하는건 return 값에 대한 보장이 되지 않기때문에 앞으로 작업시에는 조금 번거롭더라도 권장되는 방법을 사용해야한다.
따라서 되도록 비동기 처리 후 결과값을 callback 받아서 처리하도록 스크립트를 구성해야 하고 만약 callback 을 받고 return 값을 별도로 받아서 처리를 해야 한다면 아래의 소스코드를 이용하면 된다. (async/await)
// 동기처리를 위한 ajax 함수
async function ajax(req){
var res = {msg : '', err : '', always:''};
try{
await $.ajax(req)
.done(function(e){
if( e.rst == 'success'){
res.msg = '성공';
}
else{
res.msg = '실패';
}
})
.always(function(e){
res.always = 'success';
});
}catch(e){
res.msg = '에러';
res.err = e.responseText;
}
return res;
}
// ajax에서 처리된 결과값을 받기
var ret = ajax({url:'/shop/pay',dataType:'json'});
ret.then(function(e){
alert(e.msg);
console.log(e);
});
console.log('처리중입니다. 잠시만 기다려주세요.');
위의 ajax 함수 부분을 보면 앞에 async 문법으로 함수가 선언되어있다. 이는 await 문법을 사용하기 위해서 반드시 필요한 부분으로 비동기 함수를 정의하고 결과값을 받아야 하는 곳 앞에 await 을 붙이면 된다. 즉 await 는 결과값을 받을때까지 대기하는 역할을 수행한다.
또한 ajax 전송 후 done(성공처리) , always(통신성공) 처리를 해주었는데 늘상 쓰던 fail(실패처리) 은 제외되었다. 그 이유중 하나가 await 을 쓰게되면 전송된 URL에서 프로그램 에러가 발생시 fail로는 받을 수 없기에 try~catch 를 이용하여 catch 에서 오류처리를 해야한다.
최종결과는 then 을 이용하여 처리를 해주었고 결과값은 당연히 ajax 함수에서 최종 처리한 return 값을 받을 수 있다. 이번편에서 소개한 방법은 간단하게 사용방법을 보여주기 위한 소스이니 실제 사용시에는 해당 소스를 좀더 개선해서 사용하길 바란다.