從零開始封裝一個ajax框架

寫這篇文章的初衷:寫了5年代碼,發現天天的工做都是在像拼積木同樣,拼湊着一個又一個功能,可是基本的實現原理可能就那幾把刷子,想着想着就乾脆整理成一個本身風格的公共庫,既然說了,那就幹唄~javascript

先把最經常使用的一個方法---ajax入手,發現認真去作一件事情還真的不容易,因此就把這個封裝ajax的過程整理成一個博客,供你們參考,小弟也虛心聽取各位大佬建議~~~php

框架起步

框架的封裝是一個開發者綜合能力的一個體現,由於框架的封裝不只關係到怎麼讓使用者更方便的去使用你封裝的這個方法,更須要一個開發者從原理上去了解爲了實現這種方法所進行的每一步操做,每個方法的有效性,能不能用更精簡的語句實現,能不能用更高效的方法實現,或者是爲了追求某方面的性能而犧牲某方面的體驗等等... 暫時想不到好的名字,暫時把框架命名爲fly.jshtml

框架封裝的原則

根據jquery的源碼,可見我們這個框架的封裝通常包括兩個原則:java

  • 用匿名函數將腳本包起來jquery

    (function(){
    
     })()
    複製代碼
  • 使用命名空間(多級) 爲了防止全局變量命名衝突,我們使用多級命名空間來避免和項目變量衝突 因此採用F.T,同時由於我們暫時實現的是工具類庫(Util),未來有可能還有UI庫,或者其餘專門處理String、Object的類庫,因此我們來個F.T.Utilgit

    • 框架的別名FLY、F、fly等等
    • 框架的一些信息 好比框架名、版本號、項目地址[github]、做者信息等等

給你們看一下初始代碼長成什麼樣,寫好後呢,將我們的FLY掛載到windows上github

(function(FLY) {
    /** * fly.js * 版本: 1.0.0 * fly.js儘可能覆蓋開發過程當中的常見的場景,提升開發效率 * 博客: https://blog.csdn.net/qtfying * 掘金: https://juejin.im/user/57deadcd0e3dd90069721916 * QQ: 2811132560 * 郵箱: qtfying@gamil.com */
    F = fly = f = FLY;
    F.T = F.T || {};
    F.T.Util = F.T.Util || {};
    var util = F.T.Util;
})(window.FLY = window.fly || {});
複製代碼

測試工具庫是否正常引入

既然框架已經起步,就要先測試一下框架是否能用,我們先寫一個test函數測試一下能不能正常的使用:ajax

util.test = function () {
    console.log('引入fly.js框架成功');
};
複製代碼

而後呢,我們在html界面調用一下,看下可否正常執行便可,固然很完美,我們接着下一步 ~json

new XMLHttpRequest()

屬性

一個爲向服務器發送請求和解析服務器響應提供了流暢的接口。 ajax是一個老生常談的問題,可是確定有一部分人只是知道ajax而不知道XMLHttpRequest,亦或者是在框架橫行的世代,爲了發一個請求而又不得不把jquery而引入了進來,其實ajax是jquery是爲了方便你們使用而封裝的一個好用而又方便實用的一個著名的超過 XMLHttpRequest本尊的請求工具,在ES6的Fetch請求以前,發送一個完整的請求通常狀況下包括5個步驟:windows

  • 建立XMLHttpRequest對象(瀏覽器兼容性)
  • 註冊回調函數
  • 建立請求,指定請求類型、地址、異步/同步
  • 發送請求
  • 異步獲取響應數據,並利用js與DOM進行頁面局部刷新

實現步驟

//步驟一:建立異步對象
var ajax = new XMLHttpRequest();
//步驟二:設置請求的url參數,參數一是請求的類型,參數二是請求的url,能夠帶參數,動態的傳遞參數starName到服務端
ajax.open('get','getStar.php?starName='+name);
//步驟三:發送請求
ajax.send();
//步驟四:註冊事件 onreadystatechange 狀態改變就會調用
ajax.onreadystatechange = function () {
  //步驟五 若是可以進到這個判斷 說明 數據 完美的回來了,而且請求的頁面是存在的
   if (ajax.readyState == 4 &&ajax.status==200) {
  console.log(ajax.responseText); // 輸入相應的內容
  }
}
複製代碼

readyState

裏面這個readyState都有哪些含義呢:

  • 0:請求未初始化(尚未調用 open())。
  • 1:請求已經創建,可是尚未發送(尚未調用 send())。
  • 2:請求已發送,正在處理中(一般如今能夠從響應中獲取內容頭)。
  • 3:請求在處理中;一般響應中已有部分數據可用了,可是服務器尚未完成響應的生成。
  • 4:響應已完成;您能夠獲取並使用服務器的響應了。

status

響應的HTTP 狀態。

如 200 表示成功,而 404 表示 "Not Found" 錯誤。當 readyState 小於 3 的時候讀取這一屬性會致使一個異常。

statusText

HTTP 狀態的說明。

當狀態爲 200 的時候它是 "OK",當狀態爲 404 的時候它是 "Not Found"。和 status 屬性同樣,當 readyState 小於 3 的時候讀取這一屬性會致使一個異常。

responseText

做爲響應主體被返回的文本。

若是 readyState 小於 3,這個屬性就是一個空字符串。當 readyState 爲 3,這個屬性返回目前已經接收的響應部分。若是 readyState 爲 4,這個屬性保存了完整的響應體。

responseXML

若是響應的內容類型是"text/xml"或"application/xml",這個屬性將保存着響應數據的XML DOM文檔。

send()

做用:發送請求,參數爲發送的請求體,不傳請求體的話最好傳個null

open()

做用:初始化請求

xhr.open(method,url,async,user,password)

  • method 請求方式,如get,post,put等等
  • url 請求路徑,能夠是相對路徑也能夠是絕對
  • async 是否異步請求 傳佈爾值,默認true
  • user 用戶名,可選參數,爲受權使用;默認參數爲空string.
  • password 密碼,可選參數,爲受權使用;默認參數爲空string.

總是這樣寫也不是辦法啊,寫出精神ICU的節奏啊,這時候,簡單而又明瞭的寫法出來了:

$.ajax({
    type: "GET",
    url: "getUser",
    data: {id: val},   // 看後臺要什麼格式的,是字符串仍是對象 JSON.stringify(obj)
    success: function(data){},
    error: function(){},
});
複製代碼

封裝ajax

$.ajax中的一個對象,包含type、url、data、success、error大大的精簡了代碼的寫法,簡單明瞭 ~ 我們本身手動實現一個ajax方法的話,須要考慮哪些方面呢,結合jquery的源碼,而且和原生的XMLHttpRequest()方法對比,根據我們實際開發的經驗,一個完整的請求包括:

  • json數據,包括url、type、data、succFn、errorFn
  • 處理data中的參數,即將data對象拼接到url
  • 請求超時的處理
  • get方法和post方法

首先我們先把第2項處理掉,怎麼將譬如{name: 'yeyu', age: 18}轉化爲?name=yeyu&age=18這樣的字符串呢:

/** * 將參數轉拼接爲url連接後的傳參 * @returns {{String}} */
util.json2url = function(json) {
  var arr = [];
  for(var name in json) {
    arr.push(name + '=' +json[name]);
  }
  return arr.join('&');
};
複製代碼

接下來我就直接把封裝好的ajax方法貼出來,供你們參考:

/** * 結合jquery,從新封裝ajax * @returns {{responseText}} */
util.ajax = function (json) {
  var timer = null;
  json = json || {};
  if (!json.url) {
    alert('請求url不存在,請從新檢查');
    return;
  }
  json.type = json.type || 'get';
  json.time = json.time || 10;
  json.data = json.data || {};
  var _Ajax = new XMLHttpRequest();
  switch (json.type.toLowerCase()) {
    case 'get':
      _Ajax.open('GET', json.url + '?' + util.json2url(json.data), true);
      _Ajax.send();
      break;
    case 'post':
      _Ajax.open('POST', json.url, true);
      _Ajax.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
      oAjax.send(util.json2url(json.data));
      break;
  }
  _Ajax.onreadystatechange = function() {
    if (_Ajax.readyState == 4) {
      if (_Ajax.status >= 200 && _Ajax.status < 300 || _Ajax.status == 304) {
        clearTimeout(timer);
        json.succFn && json.succFn(_Ajax.responseText);
      } else {
        clearTimeout(timer);
        json.errFn && json.errFn(_Ajax.status);
      }
    }
  };
  timer = setTimeout(function() {
    alert('請求超時,請從新處理 ~ ');
    _Ajax.onreadystatechange = null;
  }, json.time * 1000);
};
複製代碼

到這裏我們就實現了一個ajax的方法,而不用由於僅僅使用ajax而將jquery引入到項目中

最後呢,再封裝兩個方法,一個post,一個get,這樣基本上就知足了咱們項目中經常使用的請求

/** * post請求 * @returns {{responseText}} */
util.post = function (jsonData) {
  ajax({
    url: jsonData.url,
    data: jsonData.data,
    succFn: jsonData.succFn,
    errFn: jsonData.errFn,
    type: 'post'
  });
};
複製代碼
/** * get請求 * @returns {{responseText}} */
util.get = function (jsonData) {
  util.ajax({
    url: jsonData.url,
    data: jsonData.data,
    succFn: jsonData.succFn,
    errFn: jsonData.errFn,
    type: 'get'
  });
};
複製代碼

到這裏,完整的ajax請求就結束了~~~

相關文章
相關標籤/搜索