深刻淺出Ajax

原文(個人GitHub):https://github.com/liangfengbo/frontend-ability/issues/1javascript

學習大綱

  1. 理解Ajax的工做原理
  2. Ajax核心-XMLHttpRequest對象
  3. 封裝Ajax方法
  4. Ajax優缺點
  5. Ajax適應場景
  6. Ajax系列面試題總結

Ajax的工做原理

含義:

1. w3chool官網:Ajax 是一種在無需從新加載整個網頁的狀況下,可以更新部分網頁的技術。
2. 個人理解:無須刷新頁面便可從服務器取得數據的技術。

原理:

Ajax的工做原理至關於在用戶和服務器之間加了—箇中間層,使用戶操做與服務器響應異步化。並非全部的用戶請求都提交給服務器,像—些數據驗證和數據處理等都交給Ajax引擎本身來作, 只有肯定須要從服務器讀取新數據時再由Ajax引擎代爲向服務器提交請求。html

ajax

核心XMLHttpRequest對象

Ajax技術的核心是XMLHttpRequest對象。
  • IE5 XHR對象是經過MSXML庫中的一個ActiveX對象實現的,因此要考慮作兼容。
  • IE7+、Firefox、Opera、Chrome和Safari都支持原生的XHR對象
new ActiveXObject(versions);

new XMLHttpRequest();

XMLHttpRequest 對象方法描述

方法 描述
abort() 中止當前請求
getAllResponseHeaders() 把HTTP請求的全部響應首部做爲鍵/值對返回
getResponseHeader("header") 返回指定首部的串值
open("method","URL",[asyncFlag],["userName"],["password"]) 創建對服務器的調用。method參數能夠是GET、POST或PUT。url參數能夠是相對URL或絕對URL。這個方法還包括3個可選的參數,是否異步,用戶名,密碼
send(content) 向服務器發送請求
setRequestHeader("header", "value") 把指定首部設置爲所提供的值。在設置任何首部以前必須先調用open()。設置header並和請求一塊兒發送 ('post'方法必定要 )

XMLHttpRequest 對象屬性描述

屬性 描述
onreadystatechange 狀態改變的事件觸發器,每一個狀態改變時都會觸發這個事件處理器,一般會調用一個JavaScript函數
readyState 請求的狀態。有5個可取值:0 = 未初始化,1 = 正在加載,2 = 已加載,3 = 交互中,4 = 完成
responseText 服務器的響應,返回數據的文本。
responseXML 服務器的響應,返回數據的兼容DOM的XML文檔對象 ,這個對象能夠解析爲一個DOM對象。
responseBody 服務器返回的主題(非文本格式)
responseStream 服務器返回的數據流
status 服務器的HTTP狀態碼(如:404 = "文件末找到" 、200 ="成功" ,等等)
statusText 服務器返回的狀態文本信息 ,HTTP狀態碼的相應文本(OK或Not Found(未找到)等等)

XMLHttpRequest進度事件

事件 描述
loadstart 在接收到響應數據的第一個字節時觸發。
progress 在接收響應期間持續不斷地觸發。
error 在請求發生錯誤時觸發。
abort 在由於調用abort()方法而終止鏈接時觸發。
load 在接收到完整的響應數據時觸發。
loadend 在通訊完成或者觸發error、abort或load事件後觸發。

封裝ajax方法

/**
 * 建立Ajax
 * @param options
 */
function Ajax(options) {
  // 新建一個對象,用途接受XHR對象
  var xhr = null;

  // 第一步建立XMLHttpRequest對象 || 同時兼任IE
  // 首先檢測原生XHR對象是否存在,若是存在則返回它的新實例
  if (typeof XMLHttpRequest != "undefined") {
    xhr = new XMLHttpRequest();

    // 而後若是原生對象不存在,則檢測ActiveX對象
  } else if (typeof ActiveXObject != "undefined") {

    // 若是存在,則建立他的對象,但這個對象須要一個傳入參數,以下:
    if (typeof arguments.callee.activeXString != 'string') {
      // 對象版本
      var versions = [
        'Microsoft.XMLHTTP',
        'Msxml2.XMLHTTP.7.0',
        'Msxml2.XMLHTTP.6.0',
        'Msxml2.XMLHTTP.5.0',
        'Msxml2.XMLHTTP.4.0',
        'MSXML2.XMLHTTP.3.0',
        'MSXML.XMLHTTP'
      ], i, len;

      for (i = 0, len = versions.length; i < len; i++) {
        try {
          // 須要versions數組中的某個項,數組的7個項分別對應7個版本.
          new ActiveXObject(versions[i]);

          // arguments是javascript函數的內置對象,表明傳入參數的集合,
          // callee就表明對象自己即new createXHR
          arguments.callee.activeXString = versions[i];
          break;

        } catch (e) {
          // 跳過
        }
      }
    }
    // 直到循環建立成功爲止,而後給本身添加一個屬性叫activeXString
    xhr = new ActiveXObject(arguments.callee.activeXString);

  } else {
    // 若是這兩種對象都不存在,就拋出一個錯誤
    throw new Error('No XHR object available');
  }

  /**
   ** options形參解析:
   * data 發送的參數,格式爲對象類型
   * url 發送請求的url,服務器地址(api)
   * async 否爲異步請求,true爲異步的,false爲同步的
   * method http鏈接的方式,包括POST和GET兩種方式
   */
  options = options || {};
  options.success = options.success || function () {
  };
  options.fail = options.fail || function () {
  };

  var data = options.data,
       url = options.url,
       async = options.async === undefined ? true : options.async,
       method = options.method.toUpperCase(),
       dataArr = [];

  // 遍歷參數
  for (var k in data) {
    dataArr.push(k + '=' + data[k]);
  }

  // GET請求
  if (method === 'GET') {
    url = url + '?' + dataArr.join('&');
    xhr.open(method, url.replace(/\?$/g, ''), async);
    xhr.send();
  }

  // POST請求
  if (method === 'POST') {
    xhr.open(method, url, async);
    xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    xhr.send(dataArr.join('&'));
  }

  // 響應接收完畢後將觸發load事件
  xhr.onload = function () {

    /**
     * XHR對象的readyState屬性
     * 0:未初始化。還沒有調用open()方法。
     * 1:啓動。已經調用open()方法,但還沒有調用send()方法。
     * 2:發送。已經調用send()方法,但還沒有接收到響應。
     * 3:接收。已經接收到部分響應數據。
     * 4:完成。已經接收到所有響應數據,並且已經能夠在客戶端使用了。
     */
    if (xhr.readyState == 4) {
      // 獲得響應
      if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
        // 處理成功數據
        var res;
        if (options.success && options.success instanceof Function) {
          res = xhr.responseText;
          if (typeof res === 'string') {
            res = JSON.parse(res);
            options.success.call(xhr, res);
          }
        }
      } else {
        // 處理錯誤數據
        if (options.fail && options.fail instanceof Function) {
          options.fail.call(xhr, res)
        }
      }

    } else {
      // 拋出檢測XHR對象的readyState屬性
      console.log('XHR was readyState:', xhr.readyState);
    }
  }
}

options參數說明

參數 類型 描述 默認值 是否填
url string 發送請求的url,服務器地址(api) '' 必填
method string http鏈接的方式,包括POST和GET兩種方式 true 選填
async boolean 是否爲異步請求,true爲異步的,false爲同步的 true 選填
data json 發送的參數,格式爲對象(json)類型 null 選填
success function 請求成功回調函數 function () { } 必填
fail function 請求失敗回調函數 function () { } 必填

示例:

Ajax({
  url: 'http://localhost:3000/api/v1/article',
  method: 'GET',
  async: true,
  success: function (res) {
    console.log('successful', res);
  },
  fail: function (err) {
    console.log('fail', err);
  }
})

成功返回數據:

successful {code: 200, msg: "查詢文章列表成功!", data: {…}}

ajax-1

ajax-2

Ajax優勢

1.無刷新更新數據。

AJAX最大優勢就是能在不刷新整個頁面的前提下與服務器通訊維護數據。這使得Web應用程序更爲迅捷地響應用戶交互,並避免了在網絡上發送那些沒有改變的信息,減小用戶等待時間,帶來很是好的用戶體驗。前端

2.異步與服務器通訊。

AJAX使用異步方式與服務器通訊,不須要打斷用戶的操做,具備更加迅速的響應能力。優化了Browser和Server之間的溝通,減小沒必要要的數據傳輸、時間及下降網絡上數據流量。java

3.前端和後端負載平衡。

AJAX能夠把之前一些服務器負擔的工做轉嫁到客戶端,利用客戶端閒置的能力來處理,減輕服務器和帶寬的負擔,節約空間和寬帶租用成本。而且減輕服務器的負擔,AJAX的原則是「按需取數據」,能夠最大程度的減小冗餘請求和響應對服務器形成的負擔,提高站點性能。git

4.基於標準被普遍支持。

AJAX基於標準化的並被普遍支持的技術,不須要下載瀏覽器插件或者小程序,但須要客戶容許JavaScript在瀏覽器上執行。隨着Ajax的成熟,一些簡化Ajax使用方法的程序庫也相繼問世。一樣,也出現了另外一種輔助程序設計的技術,爲那些不支持JavaScript的用戶提供替代功能。github

5.界面與應用分離。

Ajax使WEB中的界面與應用分離(也能夠說是數據與呈現分離),有利於分工合做、減小非技術人員對頁面的修改形成的WEB應用程序錯誤、提升效率、也更加適用於如今的發佈系統。面試

Ajax缺點

1.AJAX幹掉了Back和History功能,即對瀏覽器機制的破壞。

在動態更新頁面的狀況下,用戶沒法回到前一個頁面狀態,由於瀏覽器僅能記憶歷史記錄中的靜態頁面。一個被完整讀入的頁面與一個已經被動態修改過的頁面之間的差異很是微妙;用戶一般會但願單擊後退按鈕可以取消他們的前一次操做,可是在Ajax應用程序中,這將沒法實現ajax

2.AJAX的安全問題

JAX技術給用戶帶來很好的用戶體驗的同時也對IT企業帶來了新的安全威脅,Ajax技術就如同對企業數據創建了一個直接通道。這使得開發者在不經意間會暴露比之前更多的數據和服務器邏輯。Ajax的邏輯能夠對客戶端的安全掃描技術隱藏起來,容許黑客從遠端服務器上創建新的攻擊。還有Ajax也難以免一些已知的安全弱點,諸如跨站點腳步攻擊、SQL注入攻擊和基於Credentials的安全漏洞等等數據庫

3.對搜索引擎支持較弱。

對搜索引擎的支持比較弱。若是使用不當,AJAX會增大網絡數據的流量,從而下降整個系統的性能。json

4.破壞程序的異常處理機制。

至少從目前看來,像Ajax.dll,Ajaxpro.dll這些Ajax框架是會破壞程序的異常機制的。關於這個問題,曾在開發過程當中遇到過,可是查了一下網上幾乎沒有相關的介紹。後來作了一次試驗,分別採用Ajax和傳統的form提交的模式來刪除一條數據……給咱們的調試帶來了很大的困難

5.AJAX不能很好支持移動設備。

一些手持設備(如手機、PDA等)如今還不能很好的支持Ajax,好比說咱們在手機的瀏覽器上打開採用Ajax技術的網站時,它目前是不支持的。

Ajax適用場景

  • 表單驅動的交互
  • 深層次的樹的導航
  • 快速的用戶與用戶間的交流響應
  • 相似投票、yes/no等無關痛癢的場景
  • 對數據進行過濾和操縱相關數據的場景
  • 普通的文本輸入提示和自動完成的場景

Ajax不適用場景

  • 部分簡單的表單
  • 搜索
  • 基本的導航
  • 替換大量的文本
  • 對呈現的操縱

Ajax常見面試題:

一、Ajax是什麼?如何建立一個Ajax?

Ajax並不算是一種新的技術,全稱是asychronous javascript and xml,能夠說是已有技術的組合,主要用來實現客戶端與服務器端的異步通訊效果,實現頁面的局部刷新,早期的瀏覽器並不能原生支持ajax,可使用隱藏幀(iframe)方式變相實現異步效果,後來的瀏覽器提供了對ajax的原生支持

使用ajax原生方式發送請求主要經過XMLHttpRequest(標準瀏覽器)、ActiveXObject(IE瀏覽器)對象實現異步通訊效果

基本步驟:

var xhr =null;//建立對象 

if(window.XMLHttpRequest){

xhr = new XMLHttpRequest();

}else{

xhr = new ActiveXObject("Microsoft.XMLHTTP");

}

xhr.open(「方式」,」地址」,」標誌位」);//初始化請求 

xhr.setRequestHeader(「」,」」);//設置http頭信息 

xhr.onreadystatechange =function(){}//指定回調函數 

xhr.send();//發送請求

js框架(jQuery/EXTJS等)提供的ajax API對原生的ajax進行了封裝,熟悉了基礎理論,再學習別的框架就會駕輕就熟,好多都是換湯不換藥的內容

二、同步和異步的區別?

同步:阻塞的

  • 張三叫李四去吃飯,李四一直忙得不停,張三一直等着,直到李四忙完兩我的一塊去吃飯,瀏覽器向服務器請求數據,服務器比較忙,瀏覽器一直等着(頁面白屏),直到服務器返回數據,瀏覽器才能顯示頁面

異步:非阻塞的

  • 張三叫李四去吃飯,李四在忙,張三說了一聲而後本身就去吃飯了,李四忙完後本身去吃,瀏覽器向服務器請求數據,服務器比較忙,瀏覽器能夠自如的幹原來的事情(顯示頁面),服務器返回數據的時候通知瀏覽器一聲,瀏覽器把返回的數據再渲染到頁面,局部更新

三、如何解決跨域問題?

理解跨域的概念:協議、域名、端口都相同才同域,不然都是跨域

出於安全考慮,服務器不容許ajax跨域獲取數據,可是能夠跨域獲取文件內容,因此基於這一點,能夠動態建立script標籤,使用標籤的src屬性訪問js文件的形式獲取js腳本,而且這個js腳本中的內容是函數調用,該函數調用的參數是服務器返回的數據,爲了獲取這裏的參數數據,須要事先在頁面中定義回調函數,在回調函數中處理服務器返回的數據,這就是解決跨域問題的主流解決方案

四、頁面編碼和被請求的資源編碼若是不一致如何處理?

對於ajax請求傳遞的參數,若是是get請求方式,參數若是傳遞中文,在有些瀏覽器會亂碼,不一樣的瀏覽器對參數編碼的處理方式不一樣,因此對於get請求的參數須要使用encodeURIComponent函數對參數進行編碼處理,後臺開發語言都有相應的解碼api。對於post請求不須要進行編碼

五、簡述ajax的過程。

  1. 建立XMLHttpRequest對象,也就是建立一個異步調用對象
  2. 建立一個新的HTTP請求,並指定該HTTP請求的方法、URL及驗證信息
  3. 設置響應HTTP請求狀態變化的函數
  4. 發送HTTP請求
  5. 獲取異步調用返回的數據
  6. 使用JavaScript和DOM實現局部刷新

六、闡述一下異步加載JS。

  1. 異步加載的方案: 動態插入 script 標籤
  2. 經過 ajax 去獲取 js 代碼,而後經過 eval 執行
  3. script 標籤上添加 defer 或者 async 屬性
  4. 建立並插入 iframe,讓它異步執行 js

七、請解釋一下 JavaScript的同源策略。‘’

同源策略是客戶端腳本(尤爲是Javascript)的重要的安全度量標準。它最先出自Netscape Navigator2.0,其目的是防止某個文檔或腳本從多個不一樣源裝載。所謂同源指的是:協議,域名,端口相同,同源策略是一種安全協議,指一段腳本只能讀取來自同一來源的窗口和文檔的屬性。

八、GET和POST的區別,什麼時候使用POST?

GET:通常用於信息獲取,使用URL傳遞參數,對所發送信息的數量也有限制,通常在2000個字符,有的瀏覽器是8000個字符

POST:通常用於修改服務器上的資源,對所發送的信息沒有限制

在如下狀況中,請使用 POST 請求:

  1. 沒法使用緩存文件(更新服務器上的文件或數據庫)
  2. 向服務器發送大量數據(POST 沒有數據量限制)
  3. 發送包含未知字符的用戶輸入時,POST 比 GET 更穩定也更可靠

九、ajax是什麼?ajax的交互模型?同步和異步的區別?如何解決跨域問題?

  1. 經過異步模式,提高了用戶體驗
  2. 優化了瀏覽器和服務器之間的傳輸,減小沒必要要的數據往返,減小了帶寬佔用
  3. Ajax在客戶端運行,承擔了一部分原本由服務器承擔的工做,減小了大用戶量下的服務器負載。

十、 Ajax的最大的特色是什麼。

Ajax能夠實現異步通訊效果,實現頁面局部刷新,帶來更好的用戶體驗;按需獲取數據,節約帶寬資源;

十一、ajax的缺點

一、ajax不支持瀏覽器back按鈕。

二、安全問題 AJAX暴露了與服務器交互的細節。

三、對搜索引擎的支持比較弱。

四、破壞了程序的異常機制。

十二、ajax請求的時候get和post方式的區別

get通常用來進行查詢操做,url地址有長度限制,請求的參數都暴露在url地址當中,若是傳遞中文參數,須要本身進行編碼操做,安全性較低。

post請求方式主要用來提交數據,沒有數據長度的限制,提交的數據內容存在於http請求體中,數據不會暴漏在url地址中。

1三、解釋jsonp的原理,以及爲何不是真正的ajax

Jsonp並非一種數據格式9,而json是一種數據格式,jsonp是用來解決跨域獲取數據的一種解決方案,具體是經過動態建立script標籤,而後經過標籤的src屬性獲取js文件中的js腳本,該腳本的內容是一個函數調用,參數就是服務器返回的數據,爲了處理這些返回的數據,須要事先在頁面定義好回調函數,本質上使用的並非ajax技術

1四、什麼是Ajax和JSON,它們的優缺點。

Ajax是全稱是asynchronous JavaScript andXML,即異步JavaScript和xml,用於在Web頁面中實現異步數據交互,實現頁面局部刷新。

優勢:可使得頁面不重載所有內容的狀況下加載局部內容,下降數據傳輸量,避免用戶不斷刷新或者跳轉頁面,提升用戶體驗

缺點:對搜索引擎不友好;要實現ajax下的先後退功能成本較大;可能形成請求數的增長跨域問題限制;

JSON是一種輕量級的數據交換格式,ECMA的一個子集

優勢:輕量級、易於人的閱讀和編寫,便於機器(JavaScript)解析,支持複合數據類型(數組、對象、字符串、數字)

1五、http常見的狀態碼有那些?分別表明是什麼意思?

200 - 請求成功

301 - 資源(網頁等)被永久轉移到其它URL

404 - 請求的資源(網頁等)不存在

500 - 內部服務器錯誤

1六、一個頁面從輸入 URL到頁面加載顯示完成,這個過程當中都發生了什麼?

分爲4個步驟:

  1. 當發送一個 URL 請求時,無論這個 URL 是 Web 頁面的 URL 仍是 Web 頁面上每一個資源的 URL,瀏覽器都會開啓一個線程來處理這個請求,同時在遠程 DNS 服務器上啓動一個 DNS 查詢。這能使瀏覽器得到請求對應的 IP 地址。
  2. 瀏覽器與遠程 Web 服務器經過 TCP 三次握手協商來創建一個 TCP/IP 鏈接。該握手包括一個同步報文,一個同步-應答報文和一個應答報文,這三個報文在 瀏覽器和服務器之間傳遞。該握手首先由客戶端嘗試創建起通訊,然後服務器應答並接受客戶端的請求,最後由客戶端發出該請求已經被接受的報文。
  3. 一旦 TCP/IP 鏈接創建,瀏覽器會經過該鏈接向遠程服務器發送 HTTP 的 GET 請求。遠程服務器找到資源並使用 HTTP 響應返回該資源,值爲 200 的 HTTP 響應狀態表示一個正確的響應。
  4. 此時,Web 服務器提供資源服務,客戶端開始下載資源。

1七、ajax請求的時候get和post方式的區別

get通常用來進行查詢操做,url地址有長度限制,請求的參數都暴露在url地址當中,若是傳遞中文參數,須要本身進行編碼操做,安全性較低。

post請求方式主要用來提交數據,沒有數據長度的限制,提交的數據內容存在於http請求體中,數據不會暴漏在url地址中。

1八、ajax請求時,如何解釋json數據
使用eval() 或者JSON.parse() 鑑於安全性考慮,推薦使用JSON.parse()更靠譜,對數據的安全性更好。

參考文檔

JavaScript高級程序設計第三版
AJAX工做原理及其優缺點
Ajax原理以及優缺點
Ajax的工做原理
Ajax系列面試題總結01

相關文章
相關標籤/搜索