網絡請求發展介紹

本文講解瀏覽器請求的發展歷程,從傳統web應用到ajax,再到jquery,直到目前最爲流行的axios。(重點詳細講,沒用過的寫個思想)javascript

1、傳統web應用

傳統的網頁(不使用 AJAX)若是須要更新內容,必需重載整個網頁。過程是用戶在客戶端觸發HTTP請求,服務器處理請求並返回新的HTHL頁到客戶端,客戶端再從新讀取整個頁面。即便很小的交互,也要完成上述過程,致使浪費帶寬且交互響應很慢。vue

在這個背景下,出現了能夠更新部分網頁數據的Ajax技術。java

2、Ajax

1. 概念

AJAX即 Asynchronous JavaScript and XML。它不是新的編程語言,而是在不從新加載整個頁面的狀況下,與服務端交換數據並更新部分網頁的技術。node

2. 原理

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

3. 簡單示例

Ajax 核心由 XMLHTTPRequest、JavaScript、DOM 對象組成,經過XmlHttpRequest對象來向服務器發異步請求,從服務器得到數據,而後用 JavaScript 來操做 DOM 而更新頁面。webpack

const xmlHttp = new XMLHttpRequest()
// 發送請求
xmlHttp.open('GET', 'text1.txt', true) // open(method,url,async)
xmlHttp.send()

// 響應處理
xmlHttp.onreadystatechange = function () {
  // 請求已完成,且響應就緒
  if (xmlHttp.readyState === 4  && xmlHttp.status === 200) {
    document.getElementById('div1').innerHTML = xmlHttp.responsText
  }
}
複製代碼

4. XMLHttpRequest對象

  • readyState:存有 XMLHttpRequest 的狀態。從 0 到 4 發生變化。改變時觸發onreadystatechange
    • 0: 請求未初始化
    • 1: 服務器鏈接已創建
    • 2: 請求已接收
    • 3: 請求處理中
    • 4: 請求已完成,且響應已就緒
  • status: 服務器的HTTP狀態碼
    • 200: "OK"
    • 404: 未找到頁面
    • ...

5. 優缺點

  • 優勢:ios

    • 無刷新更新數據,用戶體驗提升
    • 按需取數據,節約空間和帶寬
    • 部分工做轉嫁到客戶端,減輕服務器負擔
    • 基於標準被支持
  • 缺點:git

    • 客戶端變的複雜,容易出錯
    • 移動設備支持較差
    • 安全問題

3、Jquery

1. 背景

由於不一樣的瀏覽器對 AJAX 的實現並不相同,因此編寫統一的 AJAX 代碼相對複雜。例如IE五、IE6沒有XMLHttpRequest對象,而是ActiveXObject。github

Jqury 庫對 AJAX 進行了封裝,使得咱們能夠經過更爲簡單統一的方式實現 AJAX 功能,同時可以把這些外部數據直接載入網頁的被選元素中。web

2. 主要 API 介紹

  • $(selector).load(URL, data, callback): 從服務端獲取獲取並將數據載入到DOM元素中
  • $.get(URL,callback) : 使用 GET 方法從服務端獲取數據
  • $.post( url [, data ] [, success ] [, dataType ] ) : 經過 HTTP POST 請求從服務器上請求數據。
  • api詳情

4、Fetch

1. Why fetch

傳統ajax(指的是 XmlHttpRequest,即XHR)已經逐漸被Fetch替代。緣由:

  • Fetch語法簡單,更加語義化, 並能方便的配置請求對象。
  • 不須要引入jquery,且移動端支持較好

2. 簡單示例

fetch(url).then(function(response) {
  return response.json();
}).then(function(data) {
  console.log(data);
}).catch(function(e) {
  console.log("Oops, error");
});

// 使用 ES6 的 箭頭函數 後:
fetch(url).then(response => response.json())
  .then(data => console.log(data))
  .catch(e => console.log("Oops, error", e))
複製代碼

3. polyfill: whatwg-fetch

fetch的原生支持並很差,經過引入polyfill來支持主流瀏覽器。實質是對於不支持 fetch api 的瀏覽器,使用 XMLHttpRequest 模擬實現 fetch api。

  • 關鍵源碼:

    if (self.fetch) {
      return
    }
    ...
    self.fetch = function(input, init) {
        return new Promise(function(resolve, reject) {
          var request = new Request(input, init)
          var xhr = new XMLHttpRequest()
    
          xhr.onload = function() {...}
        }
    }
    複製代碼
  • plato((項目採用的vue腳手架)引入方法:

    // src/polyfills/index
    import 'whatwg-fetch'
    
    // webpack.config.bable.js
    entry: {
      app: [
        paths.src('polyfills/index.js'),  // 加載 polyfills
        paths.src('index.js')]  // 加載入口
    }
    複製代碼
  • 和Jquery.ajax()的區別

    • 服務器返回 404,500 錯誤碼時並不會reject,只有網絡錯誤或者其餘緣由致使請求不能完成時,fetch 纔會被 reject。爲了保證reject HTTP錯誤狀態,可作以下處理:eg:全部非2xx的錯誤碼都拋出錯誤異常。 (----- 很差用,有時候須要作處理)

      function checkStatus(response) {
        if (response.status >= 200 && response.status < 300) {
          return response
        } else {
          var error = new Error(response.statusText)
          error.response = response
          throw error
        }
      }
      
      function parseJSON(response) {
        return response.json()
      }
      
      fetch('/users')
        .then(checkStatus)
        .then(parseJSON)
        .then(function(data) {
          console.log('request succeeded with JSON response', data)
        }).catch(function(error) {
          console.log('request failed', error)
        })
      複製代碼
    • plato(項目採用的vue腳手架)實現建request.js

      const body = await getBody(res)
      if (res.status >= 200 && res.status < 400) {
        return body
      } else {
        throw body
      }
      
      async function getBody (res) {
        const type = res.headers.get('Content-Type')
      
        if (type && type.indexOf('json') !== -1) {
          return await res.json()
        }
      
        const body = await res.text()
      
        try {
          return JSON.parse(body)
        } catch (error) {
          return { body }
        }
      }
      複製代碼
  • Fetch 請求默認是不帶 cookie 的,並且也不接收cookie。

    • 發送cookie

      • 不跨域:fetch(url, {credentials: 'same-origin'})
      • CORS 跨域請求:fetch(url, {credentials: 'include'})
    • 接收cookie
      同XHR相同, 從服務端返回的響應頭Set-Cookie是一個被禁的字段,因此不能經過response.headers.get()來獲取。獲取cookie應該是瀏覽器的職責,經過document.cookie來實現。

4. fetch() 詳解

  • 語法: Promise fetch(input[, init])
  • 參數
    • input:定義要獲取的資源
    • init: 一個配置項對象,包括全部對請求的設置。可選的參數有:
      • method
      • headers
      • body
      • mode
      • credientials
      • cache
      • ...
  • 返回值: 一個 Promise,resolve 時回傳 Response 對象。

5、Axios

基於Promise的HTTP庫,用於瀏覽器端和Node.js端, 底層實現也是封裝XMLHttpRequest。

  • Why axios:

    • 支持兩端:browser, nodejs
    • 支持攔截器
    • 支持json數據自動轉換
    • 基於promise,使用簡單
    • 體積小
    • fetch 實現偏底層,一般須要封裝後使用,axios可直接用
  • 特色

    • 瀏覽器端:make XMLHttpRequest
    • Nodejs:make http request
    • 支持promise api
    • 支持請求 intercept、響應intercept
    • 自動轉換JSON數據

參考:

5、參考

相關文章
相關標籤/搜索