반응형

개발을하다보면 ajax 방식의

동기 처리가 필요할 때가있다

동기 비동기에 대해서 간단히 짚고 넘어가자면

동기방식은 간단하게 생각하자면 JAVA 코드처럼 수행방식이 

위에서 아래로 순서적으로 코드 한줄 한줄을 읽어 나가는 방식이다

예시를 들 필요가 없는게 비동기방식이 예시때문에 헷갈린적이있었다

비동기 방식은 수행방식이 한줄 한줄 읽어 가는것은 맞지만 시간이 걸리는 코드는 기다려주지않고 

건너 뛰어서 다음 코드를 하나씩 수행하게된다

동기와 비동기의 중간에 3초가 걸리는 test() 함수가 하나있다고 생각해보면


-동기방식은 3초 test함수를 실행한 뒤에 다음 코드를 수행하지만


-비동기방식은 3초 test함수를 기다리지않고 다음코드를 계속 실행하게된다


스크립트 예시를 들어보면


- <img> 태그를 name 순서로 만들어주는 함수 A()

- 이미지 태그안에 링크를 붙여주는 함수 B()

가 있다고 가정해보자

코드 순서는

A();

B();

로 했다고 보면

자바스크립트에선 A() 함수가 시간이 걸린다면 건너뛰어버리고 간헐적으로

B() 함수가 먼저 실행되어 이미지가 깨져버리거나 에러가 발생한다



서버단의 로직을 태워오는 ajax 가 이런 문제가 종종 발생하게되는데

이걸 방지할수있는 promise 코드가 있다 

패턴 예제가 다양하지만 직접 사용해 보았던 패턴만 확인해볼 예정이다


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//ajax + promise 예제
    var jsonData = {"STATUS":"A","MATRL":"A0000001","main":['a','b','c','d'],"stringObj":"{\"이름\":\"덩치\",\"거주지\":\"서울\"}"};
    
    var promise = $.ajax({  
        type: "POST",
        url: "/test/go",
        dataType: "json",    
        traditional: true,//배열 객체 보낼때
        data: jsonData });
    
    promise.done(successFunction);//프로미스 패턴 => 해당 ajax를 태운다음에 동작하는 function(동기방식)
    promise.fail(failFunction);
    
    function successFunction(data){
        if(data.result ==='success')
            var a = "함수호출 success";    
        
        return alert(a);
    }
    
    function failFunction(data){
        if(data.result !='success')
            var a = "함수호출 fail";    
        return alert(a);
    }
cs


successFunction 에 다음 작업을 넣어주면 임시적으로 동기처리를 할수있게된다


when 이라는 함수도 사용할수있다

여러가지 함수를 실행시킬수있는 방법으로 done 전에 실행된다 


1
2
3
$.when(A(), B()).done(function(result1, result2) {
  console.log(result1, result2);
});
cs



구글링을 해보면 나오는 async: false 옵션을 주는 방법은

jquery 1.8 버전부터 막혀서 권장되지않는 방법이다.




기존에 promise 패턴이 아닌 callback 방식의 경우에는 아래와 같이 코딩을 하였습니다.

$.ajax({
  url: "/ServerResource.txt",
  success: successFunction,
  error: errorFunction
});


대부분 함수의 파라미터 객체에 function 을 설정하여 결과에 대한 처리를 했습니다. 이러한 경우 callback 이 중첩되어 소스의 가독성도 떨어질 뿐더러 관리가 안되는 단점이 있었습니다.



jQuery 1.5 버전 이후부터는 아래와 같이 done()fail()always() 를 이용하여 결과에 대한 처리를 지정합니다.

var promise = $.ajax({
  url: "/ServerResource.txt"
});
  
promise.done(successFunction);
promise.fail(errorFunction);
promise.always(alwaysFunction);


jQuery.ajax() 는 jQuery XMLhttpRequest(jqXHR) 을 반환하기 때문에 아래와 같은 방식으로도 구현이 가능합니다.

$.ajax( "example.php" )    
    .done(function() { alert("success"); })    
    .fail(function() { alert("error"); })    
    .always(function() { alert("complete"); }); 


체인 방식이 아니더라도 jqXHR 객체에 직접 지정도 가능합니다.

var jqxhr = $.ajax( "example.php" )    
    .done(function() { alert("success"); })    
    .fail(function() { alert("error"); })    
    .always(function() { alert("complete"); }); 
     
    // perform some work here ... 
     
    // Set another completion function for the request above
    jqxhr.always(function() { alert("another complete"); });



jQuery 1.8 버전 이후부터는 then() 함수를 사용하여 Promise 패턴을 적용할 수 있습니다.

then() 의 첫번째 인자는 성공에 대한 액션, 두번째 인자에는 실패에 대한 액션을 지정할 수 있습니다.

$.ajax({url: "/ServerResource.txt"}).then([successFunction1, successFunction2, successFunction3], 
                                          [errorFunction1, errorFunction2]);
 
//same as
 
var jqxhr = $.ajax({
  url: "/ServerResource.txt"
});
  
jqxhr.done(successFunction1);
jqxhr.done(successFunction2);
jqxhr.done(successFunction3);
jqxhr.fail(errorFunction1);
jqxhr.fail(errorFunction2);
var promise = $.ajax({
  url: "/ServerResource.txt"
});
  
promise.then(successFunction, errorFunction);
var promise = $.ajax({
  url: "/ServerResource.txt"
});
 
promise.then(successFunction); //no handler for the fail() event




Deferred 객체를 직접 만들어서 사용할 수 있는데, 그 방법은 아래와 같습니다.


var timer;
$('#result').html('waiting…');
  
var promise = process();
promise.done(function() {
  $('#result').html('done.');
});
promise.progress(function() {
  $('#result').html($('#result').html() + '.');
});
 
function process() {
  var deferred = $.Deferred();
 
  timer = setInterval(function() {
    deferred.notify();
  }, 1000);
   
  setTimeout(function() {
     clearInterval(timer);
     deferred.resolve();
  }, 10000);
   
  return deferred.promise();
}




Promise 에 등록된 callback 들을 Deferred 가 각 상황에 맞게 호출해주는 방식입니다.


then() 함수를 이용하면 아래와 같이 구현할 수 있습니다.

var timer;
 
(function process() {
  $('#result').html('waiting…');
  var deferred = $.Deferred();
     
  timer = setInterval(function() {
    deferred.notify();
  }, 1000);
   
  setTimeout(function() {
     clearInterval(timer);
     deferred.resolve();
  }, 10000);
   
  return deferred.promise();
})().then(function() { $('#result').html('done.'); },
          null,
          function() { $('#result').html($('#result').html() + '.'); });



References

http://www.htmlgoodies.com/beyond/javascript/making-promises-with-jquery-deferred.html

https://api.jquery.com/category/deferred-object/



출처: http://uwostudy.tistory.com/54 [UWO스터디]

반응형

'IT > Javascript|Jquery' 카테고리의 다른 글

javascript 셀렉트박스(SelectBox) 바로실행  (2) 2018.01.04
ajax 로딩시 새로고침 문제  (6) 2018.01.03
ajax 배열전송  (0) 2018.01.02
모바일/PC 코딩하기  (0) 2018.01.02
Jquery 셀렉터(Selector) 사용하기  (0) 2018.01.02

+ Recent posts