본문 바로가기

Programming Language/Javascript

[Javascript] jquery 비동기 처리 (promise, $.when.apply)

UI 단을 jquery로 개발할때 여러 rest api를 사용해서 데이터를 조합하고 화면을 그리는 일을 많이 하게 된다. 그러나 ajax로 비동기 api 호출 시 api 종료 시점을 판단하고 그때 무언가 하고 싶을때는 어떨게 하면 될까?

 

아래와 같이 rest api를 호출하는 함수가 하나 있다고 하자

 

function testCall(url) {

  $.ajax({
    type : "GET"
    ,url : url
    ,async : true
    ,dataType: null
    ,beforeSend: function (xhr) {

    }
    ,success : function(response) {
      console.log(response);
    }
    ,error : function(jqXHR, error) {
     
    }
  });

}

 

  function callTest() {
    testCall('/api/v1/test');
    testCall('/api/v1/test2');

    console.log('callTest End');
  }

 

그러나 async로 ajax call 이 되다보니 위 callTest 함수는 바로 프린트를 찍고 종료되어 버린다. 아래가 실행 로그 결과이다. callTest는 바로 로그를 찍고 종료되어 버리고 이어서 각각 api 결과가 출력되고 있다.

 

callTest End
dashboard?strId=3&userSn=736:335 {resultData: null, resultCode: '0000', resultMsg: '정상처리'}
dashboard?strId=3&userSn=736:335 {resultData: null, resultCode: '0000', resultMsg: '정상처리'}

 

위 결과는 우리가 원하는 결과가 아니다. 제일마지막에 호출이 끝난 api의 시점을 알고 그때 무언가 하고 싶다면 아래와 같이 jquery deferred, promise, when.apply 를 활용하면 같단히 끝난다.

 

아래와 같이 호출 함수를 promise를 리턴하게 바꾼다.

function testCall(url) {
  let deferred = $.Deferred();

  $.ajax({
    type : "GET"
    ,url : url
    ,async : true
    ,dataType: null
    ,beforeSend: function (xhr) {

    }
    ,success : function(response) {
      console.log(response);
      deferred.resolve();
    }
    ,error : function(jqXHR, error) {
      deferred.reject();
    }
  });

  return deferred.promise();
}

 

호출부에서는 when.apply를 사용해 실행할 promise api 리스트를 넘겨주면 모든 api의 종료 응답을 확인하고 .done함수가 호출되게 된다. 여러 api를 동시에 호출할때는 when 사용시 apply를 꼭 사용해야 한다

function callTest() {
  let functionQueue = [];

  functionQueue.push(testCall('/api/v1/test'));
  functionQueue.push(testCall('/api/v1/test2'));

  let combinedPromise = $.when.apply($, functionQueue);
  combinedPromise.done(function() {
    console.log('callTest success');
  }).fail(function() {
    console.log('callTest fail');
  });
}

 

실행결과 로그는 다음과 같다. 호출한 api들이 모두 끝난 이후에 .done 이 호출되고 로그가 찍히는 것을 볼 수 있다.

 

{resultData: null, resultCode: '0000', resultMsg: '정상처리'}
{resultData: null, resultCode: '0000', resultMsg: '정상처리'}
callTest success

 

-- The End --