AJAX API



이전 포스트에서 우리는 AJAX 대한 정의와 XHR 객체 맴버에 대해 알아보았습니다.


이번 시간에는 그 내용을 바탕으로 AJAX API 코드를 작성하고 코드에 설명해 드리도록 하겠습니다.




아래는 작성된 AJAX API 전체 소스입니다.


  1. var Ajax = (function(win, doc){
  2.    
  3.     var ua = window.navigator.userAgent.toLowerCase();
  4.  
  5.     return { request: function(opt){ return new request(opt); } };
  6.        
  7.     // 요청
  8.     function request(opt)
  9.     {
  10.  
  11.         this.options = {
  12.            
  13.             url: '',
  14.             type: 'html',
  15.             method: 'post',
  16.             headers: {},
  17.             data: {},              
  18.             callback: function(){ ; }
  19.         };
  20.  
  21.         extend.call(this.options, opt);
  22.         start.call(this.options);
  23.    
  24.         return this;
  25.     };
  26.  
  27.    
  28.     function start(){
  29.        
  30.         if (!this.url) return false;
  31.  
  32.         var xhr = getXHR()
  33.           , params = getParamsSerialize(this.data);
  34.  
  35.         var method = this.method = this.method.toLowerCase();
  36.        
  37.         var url = (method === 'get' && params) ? this.url + '?' + params + '&s=' + encodeURIComponent(new Date().toUTCString()) : this.url;
  38.        
  39.         xhr.open(method, url, true);
  40.    
  41.         setHeaders.call(xhr, this.headers);
  42.  
  43.         if (xhr.overrideMimeType) setHeaders.call(xhr, { 'Connection': 'close' });
  44.  
  45.         (function($this){ xhr.onreadystatechange = function(){ handler.call($this, xhr); }; })(this);
  46.  
  47.        
  48.         if (method === 'get') xhr.send(null);
  49.         else if (method === 'post') xhr.send(params + '&s=' + encodeURIComponent(new Date().toUTCString()));
  50.     }
  51.  
  52.  
  53.     // xhr 객체 가져오기
  54.     function getXHR(){
  55.          /*
  56.              ie5 : Microsoft.XMLHTTP,
  57.              ie6+ : Msxml2.XMLHTTP,
  58.              비 IE : XMLHttpRequest
  59.          */
  60.          if (!window.XMLHttpRequest) return new ActiveXObject(ua.indexOf('msie 5') > -1 ? 'Microsoft.XMLHTTP' : 'Msxml2.XMLHTTP');
  61.          else if (window.XMLHttpRequest) return new XMLHttpRequest;
  62.  
  63.     };
  64.  
  65.    
  66.     // 파라메터 직렬화
  67.     function getParamsSerialize(data) {
  68.      
  69.         var ret = [];
  70.  
  71.         for (var p in data) ret.push(p + '=' + encodeURIComponent(data[p]));
  72.  
  73.         return ret.join('&');
  74.     };
  75.  
  76.     // 요청 헤더 추가
  77.     function setHeaders(heders){
  78.  
  79.         for (var h in heders) if (heders[h] !== '') this.setRequestHeader(h, heders[h]);
  80.  
  81.     };
  82.  
  83.     // 응답 헨들러
  84.     function handler(x){
  85.            
  86.         if (x.readyState === 4){
  87.  
  88.             if (error(x.status)) alert('request Error' + x.status);
  89.             else this.callback.apply(x, [getXhrData.call(this, x), x.status]); 
  90.         }
  91.     };
  92.  
  93.  
  94.     // 서버 에러 유/무
  95.     function error(s){
  96.    
  97.         return !s && window.location.protocol === 'file:' ? false : s >= 200 && s < 300 ? false : s === 304 ? false : true;
  98.     };
  99.  
  100.     // 수신받은 결과값 가공 함수
  101.     function getXhrData(x)
  102.     {
  103.  
  104.         var contentType = x.getResponseHeader('content-type')
  105.           , xml = contentType && contentType.indexOf('xml') > -1
  106.           , json = contentType && contentType.indexOf('json') > -1;
  107.  
  108.         var type = this.type.toLowerCase();
  109.  
  110.         if (xml && type === 'xml') return x.responseXML;        
  111.         else if (json  && type === 'json') return eval('(' + x.responseText + ')');
  112.         else if (type === 'text') return x.responseText.replace(/<(\/)?([a-zA-Z]*)(\s[a-zA-Z]*=[^>]*)?(\s)*(\/)?>/g, '');
  113.         else return x.responseText; // html */*
  114.  
  115.     };
  116.  
  117.     // 객체 상속 함수
  118.     function extend(){
  119.        
  120.         var target = this
  121.           , opts = []
  122.           , src = null
  123.           , copy = null;
  124.  
  125.         for (var i = 0, length = arguments.length; i < length; i++) {
  126.            
  127.             opts = arguments[i];
  128.            
  129.             for (var n in opts) {
  130.                 src = target[n];
  131.                 copy = opts[n];
  132.  
  133.                 if (src === copy) continue;
  134.                 if (copy) target[n] = copy;
  135.             }
  136.         }
  137.     };
  138.  
  139. })(window, document);





API 실행 함수


  1. function ajax()
  2. {
  3.     Ajax.request({
  4.         url: 'http://sof.fpscamp.com',
  5.         type: 'text',
  6.         method: 'post',
  7.         header: {
  8.             'content-type': 'application/x-www-form-urlencoded'
  9.         },             
  10.         data: {
  11.             id: 'id1'
  12.         },
  13.         callback: function(data, status){
  14.             //alert(data);
  15.             alert(status);
  16.         }
  17.     });
  18.  
  19.     Ajax.request({
  20.         url: 'http://sof.fpscamp.com',
  21.         type: 'text',
  22.         method: 'post',
  23.         header: {
  24.             'content-type': 'application/x-www-form-urlencoded'
  25.         },             
  26.         data: {
  27.             id: 'id2'
  28.         },
  29.         callback: function(data, status){
  30.             //alert(data);
  31.             //alert(status);
  32.             alert(this.abort);
  33.         }
  34.     });
  35. };







API 맴버 설명:


- 호환 가능한 XHR 객체를 가져오는 함수이며, 즉, 브라우저(버전 포함)에 따라 반환되는 객체가 달라집니다.


  1. function getXHR(){
  2.      /*
  3.          ie5 : Microsoft.XMLHTTP,
  4.          ie6 ~ ie? : Msxml2.XMLHTTP,
  5.          표준 브라우저(IE 브라우저 제외) : XMLHttpRequest
  6.      */
  7.      if (!window.XMLHttpRequest) return new ActiveXObject(ua.indexOf('msie 5') > -1 ? 'Microsoft.XMLHTTP' : 'Msxml2.XMLHTTP');
  8.      else if (window.XMLHttpRequest) return new XMLHttpRequest;
  9.  
  10. };




- 전송 될 데이터 객체를 파라메터 문자열로 직렬화 시키는 함수


  1. function getParamsSerialize(data) {
  2.  
  3.     var ret = [];
  4.  
  5.     for (var p in data) ret.push(p + '=' + encodeURIComponent(data[p]));
  6.  
  7.     return ret.join('&');
  8. };
  9.  




- 요청 HTTP Header 정의 함수


  1. function setHeaders(heders){
  2.  
  3.     for (var h in heders) if (heders[h] !== '') this.setRequestHeader(h, heders[h]);
  4.  
  5. };




- 응답에 대한 상태값을 검증하여 완료 시 전달받은 callback 함수를 호출합니다.


  1. function handler(x){
  2.        
  3.     if (x.readyState === 4){
  4.  
  5.         if (error(x.status)) alert('request Error' + x.status);
  6.         else this.callback.apply(x, [getXhrData.call(this, x), x.status]); 
  7.     }
  8. };




응답에 대한 상태값을 확인 후 에러 유/무를 반환합니다.


  1. function error(s){
  2.  
  3.     return !s && window.location.protocol === 'file:' ? false : s >= 200 && s < 300 ? false : s === 304 ? false : true;
  4. };




- 전달받은 요청 타입과 응답 Content-Type을 비교하여 해당 Content-Type으로 가공하여 반환합니다.


  1. function getXhrData(x)
  2. {
  3.  
  4.     var contentType = x.getResponseHeader('content-type')
  5.       , xml = contentType && contentType.indexOf('xml') > -1
  6.       , json = contentType && contentType.indexOf('json') > -1;
  7.  
  8.     var type = this.type.toLowerCase();
  9.  
  10.     if (xml && type === 'xml') return x.responseXML;        
  11.     else if (json  && type === 'json') return eval('(' + x.responseText + ')');
  12.     else if (type === 'text') return x.responseText.replace(/<(\/)?([a-zA-Z]*)(\s[a-zA-Z]*=[^>]*)?(\s)*(\/)?>/g, '');
  13.     else return x.responseText; // html */*
  14.  
  15. };