JavaScript XHR的用法和自定義封裝


  2005年Jesse James Garrett發表了一篇在線文章,題為 "Ajax: A new Approach to Web Applications" 。他在這篇文章里介紹了一種技術,用他的話說,就叫 Ajax ,是對 Asynchronous JavaScript + XML 的簡寫。這一種技術,能夠向服務器請求額外的數據而無須卸載頁面,會帶來更好的用戶體驗。Carrett 還解釋了怎樣使用這一技術改變自從Web誕生以來就一直沿用的“單機,等待”的交互模式。Ajax技術的核心是 XMLHttpRequest 對象(簡稱XHR)

  IE7之前的版本,創建XHR對象只能通過下面的方法:

function createXHR () {
    if (typeof agreement.callee.activeXString != 'string' ) {
        var versions = ["MSXML2.XMLHTTP.6.0", "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP"],
        i, len;
        for (i = 0, len = versions.length; i < len; i++) {
            try (
                new ActiveXObject(versions[i]);
                arguments.callee.activeXString = versions[i];
                break;
            } catch (ex) {
                // 跳過
            }
        }
    }
    return new ActiveXObject(arguments.callee.activeXString);
}

  IE7+、 FireFox、Opera、Chrome 和 Safari 都支持原生的 XHR 對象,在這些瀏覽器中創建 XHR 對象要像下面這樣使用 XMLHttpRequest 構造函數。

var xhr = new XMLHttpRequest();

  綜合以上的情況,既支持IE的早期版本也支持IE7以及更高版本的瀏覽器,就可以這樣做:

function createXHR () {
    if (typeof XMLHttpRequest != 'undefined') {
        return new XMLHttpRequest()
    } else if (typeof ActiveXObject != 'undefined') {
      if (typeof agreement.callee.activeXString != 'string' ) {
          var versions = ["MSXML2.XMLHTTP.6.0", "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP"],
          i, len;
          for (i = 0, len = versions.length; i < len; i++) {
              try (
                  new ActiveXObject(versions[i]);
                  arguments.callee.activeXString = versions[i];
                  break;
              } catch (ex) {
                  // 跳過
              }
          }
      }
      return new ActiveXObject(arguments.callee.activeXString);
  } else {
    throw new Error('No XHR object available.');  
  }
}

  由於其他瀏覽器中對XHR的實現與IE最早的實現是兼容的,因此就可以在所有瀏覽器中都以相同方式使用這個方法創建 xhr 對象:

var xhr = new createXHR();

  在創建了 xhr 對象之后,可以調用該對象上的 open() 方法,創建一個請求。此方法有三個參數:請求類型,請求路徑,是否異步發送請求(默認為true);

  再調用該對象的 send() 方法,發送請求。如果是 post 請求則需要傳入請求參數。如:xhr.send('a=4&b=0');

  請求發送成功后,再通過監測狀態來獲取:onreadystatechange;在這個方法中監聽 xhr 的 readyState 和 status ;

  對 xhr 的封裝類似JQuery的get、post、ajax 方法。ajax方法可以是get或者post,該方法可以傳入多個參數,返回一個Promise對象。

var $ = {
    createXHR: function () {
      if (typeof XMLHttpRequest != 'undefined') {
          return new XMLHttpRequest()
      } else if (typeof ActiveXObject != 'undefined') {
        if (typeof agreement.callee.activeXString != 'string' ) {
            var versions = ["MSXML2.XMLHTTP.6.0", "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP"],
            i, len;
            for (i = 0, len = versions.length; i < len; i++) {
                try (
                    new ActiveXObject(versions[i]);
                    arguments.callee.activeXString = versions[i];
                    break;
                } catch (ex) {
                    // 跳過
                }
            }
        }
        return new ActiveXObject(arguments.callee.activeXString);
    } else {
      throw new Error('No XHR object available.');  
    }
  },
   get: function(url, data, callback, dataType) {
     // 避免dataType大小寫的問題 let dataType = dataType.toLowerCase() // 如果有傳入data,則在url后面跟上參數 if(data) { url += '?' Object.keys(data).forEach(key => url += `${key}=${data[key]}&`)     url = url.slice(0, -1)     } // 調用我們封裝的方法生成XHR對象 let xhr = this.createXHR() // 創建get請求 xhr.open('get', url) // 發送請求 xhr.send() xhr.onreadystatechange = function() { if(xhr.readyState === 4) { if(xhr.status >= 200 && xhr.status < 300 || xhr.status == 304) { // 若dataType為json,則將返回的數據通過JSON.parse格式化 let res = dataType === 'json' ? JSON.parse(xhr.responseText) : xhr.responseText // 調用回調函數,並把參數傳進去 callback(res, xhr.status, xhr) } } } }, post: function(url, data, callback, dataType) { // 避免dataType大小寫的問題 let dataType = dataType.toLowerCase() // 調用我們封裝的方法動態生成XHR對象 let xhr = this.createXHR() let str = '' // 若傳入參數,則將參數序列化 if(data) { Object.keys(data).forEach(key => str += `${key}=${data[key]}&`) str = str.slice(0, -1) } // 設置頭部信息 xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded') // 發送請求,並攜帶參數 xhr.send(str) xhr.onreadystatechange = function() { if(xhr.readyState === 4) { if(xhr.status >= 200 && xhr.status < 300 || xhr.status == 304) { // 若dataType為json,則將返回的數據通過JSON.parse格式化 let res = dataType === 'json' ? JSON.parse(xhr.responseText) : xhr.responseText // 調用回調函數,把對應參數傳進去 callback(res, xhr.status, xhr) } } } }, ajax: function(params) { // 初始化參數 let type = params.type ? params.type.toLowerCase() : 'get' let isAsync = params.isAsync ? params.isAsync : 'true' let url = params.url let data = params.data ? params.data : {} let dataType = params.dataType.toLowerCase() // 用我們封裝的方法動態生成XHR對象 let xhr = this.createXHR() let str = '' // 拼接字符串 Object.keys(data).forEach(key => str += `${key}=${data[key]}&`) str = str.slice(0, -1) // 如果是get請求就把攜帶參數拼接到url后面 if(type === 'get') url += `?${str}`; // 返回promise對象,便於外部then和catch函數調用 return new Promise((resolve, reject) => { // 創建請求 xhr.open(type, url, isAsync) if(type === 'post') { xhr.setRequestHeader('Content-Type', 'application/x-www-form-rulencoded') xhr.send(str) } else { xhr.send() } xhr.onreadystatechange = function() { if(xhr.readyState === 4) { if(xhr.status >= 200 && xhr.status < 300 || xhr.status == 304) { let res = dataType === 'json' ? JSON.parse(xhr.responseText) : xhr.responseText resolve(res) // 請求成功,返回數據 } else { reject(xhr.status) // 請求失敗,返回狀態碼 } } } }) } }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM