首頁»前端»關于前端請求的那些事

關于前端請求的那些事

來源:qianduan 發布時間:2019-08-19 閱讀次數:

 引言

  前端是一個快速發展的領域,而在前端的技術棧當中,前端請求又是最見的一個領域,通過請求接口數據,才能將一個靜態的頁面動態化。本文將以前端發展的時間軸來逐一分析前端請求的技術演變及其優劣,針對這一課題,作者查閱了相關資料加以自己的理解,如有錯誤,煩請指出。

 XMLHttpRequest

  XMLHttpRequest是最早出現的與服務器交換數據的方案,有了XMLHttpRequest,開發者終于可以在不重新加載頁面的情況下更新網頁,可以在頁面加載后請求接受以及發送數據。而所有瀏覽器均可以獲取XMLHttpRequest對象:

var xhr = new XMLHttpRequest(); //獲取xhr對象

  但是XMLHttpRequest是個比較粗燥的底層對象,各個瀏覽器對其的創建方法也不同,以下是兼容方法:

var xhr;
if (window.XMLHttpRequest) { // Mozilla, Safari...
  xhr = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE
  try {
    xhr = new ActiveXObject('Msxml2.XMLHTTP');
  } catch (e) {
    try {
      xhr = new ActiveXObject('Microsoft.XMLHTTP');  //IE5,6
    } catch (e) {}
  }
}

  使用XMLHttpRequest發起一個get請求

//get請求
xhr.open("GET","test1.txt",true);
xhr.send();

  完整的post請求代碼如下:

var xhr;
if (window.XMLHttpRequest) { // Mozilla, Safari...
  xhr = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE
  try {
    xhr = new ActiveXObject('Msxml2.XMLHTTP');
  } catch (e) {
    try {
      xhr = new ActiveXObject('Microsoft.XMLHTTP');
    } catch (e) {}
  }
}
if (xhr) {
  xhr.onreadystatechange = onReadyStateChange;
  xhr.open('POST', '/api', true);
  // 設置 Content-Type 為 application/x-www-form-urlencoded
  // 以表單的形式傳遞數據
  xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
  xhr.send('username=admin&password=root');
}


// onreadystatechange 方法
function onReadyStateChange() {
  // 該函數會被調用四次
  if (xhr.readyState === 4 &&xhr.status === 200) {
    console.log('執行成功');
  } else {
    console.log('執行出錯');
  }
}

 Jquery Ajax

  說到Jquery,這是一個時代,幾乎統治了前端10年有余,徹底解決了UI層與數據層交互的問題,直到三大框架(Angular/React/Vue)的出現,前端進入MVVM浪潮。而Ajax將XHR進行封裝,讓開發者可以更加便捷方便進行使用。

$.ajax({   //標準寫法
   type: 'POST',
   url: url,
   data: data,
   dataType: dataType,
   success: function () {},
   error: function () {}
});
$.get(url,function(){}); //get請求
$.post(url,body,function(){}); //post請求
$.getJSON(url,function(){});  //get請求從服務器加載Json編碼

  優點:

  • 對原生XHR的封裝
  • 針對MVC的編程
  • 完美的兼容性
  • 支持jsonp

  缺點:

  • 不符合MVVM
  • 異步模型不夠現代,不支持鏈式,代碼可讀性差
  • 整個Jquery太大,引入成本過高

 Fetch

  fetch其實是一個新世界,脫離的XHR,完全是基于Promise的異步處理機制,使用起來會比起ajax更加簡單。

  使用fetch的代碼會相比xhr來說更具有條理性

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))

  優點:

  • 更加底層,提供的API豐富(request, response)
  • 語法簡單,脫離了XHR,基于ES新的Promise設計

  看到以上,或許你會覺得fetch真的很美好,但是請了解,fetch本身是一個 low-level 的 API,它注定不會像你習慣的 $.ajax 或是 axios 等庫幫你封裝各種各樣的功能或實現。

  所以它是存在一定的缺點:

  • 兼容性比較凄慘,低級別瀏覽器均不支持,需要實現fetch的polyfill了。思路其實很簡單,就是判斷瀏覽器是否支持原生的fetch,不支持的話,就仍然使用XMLHttpRequest的方式實現,同時結合Promise來進行封裝。常見的polyfill就有:es6-promise,babel-polyfill,fetch-ie8等

Alt text

  • 不支持jsonp,可以引入fetch-jsonp `javascript //安裝 npm install fetch-jsonp --save-dev

  //使用 fetchJsonp(url, { timeout: 3000, jsonpCallback: 'callback' }).then(function(response) { console.log(response.json()); }).catch(function(e) { console.log(e) });

- 沒有攔截器,需要額外再封裝一層或者fetch-interceptor
- 默認不帶cookie,需要添加配置
```javascript
fetch(url,{
  credentials: 'include' //include表示cookie既可同域,也可跨域,‘same-origin’表示只可同域
});
  • 沒有abort,不支持timeout超時處理

  可以用Promise.race()實現,Promise.race(iterable) 方法返回一個Promise對象,只要 iterable 中任意一個Promise 被 resolve 或者 reject 后,外部的Promise 就會以相同的值被 resolve 或者 reject。

  • 無法獲取progress狀態

  fetch中的Response.body 中實現了getReader()方法用于讀取原始字節流, 該字節流可以循環讀取。參考javascript - Progress indicators for fetch? - Stack Overflow 2016 - the year of web streams

 Axios

  axios也是比較新的網絡請求的類庫,并且被尤雨溪尤大推薦,已成為VUE的網絡請求標配,也是十分的火爆。它本身也是對原生XHR的封裝。

  • 支持node,創建http請求
  • 支持Promise API
  • 客戶端防止CSRF:每個請求帶一個cookie拿到的key
  • 攔截請求和響應
  • 可取消請求

  兼容性上雖然axios本質上也是對原生XHR的封裝,但是它也依賴原生ES6 Promise的實現,和fetch一樣需要polyfill的兼容。

Alt text

  安裝

//npm
npm install axios

//cdn
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

  基本使用如下:

axios({
    method: 'GET',
    url: url,
})
.then(res => {console.log(res)})
.catch(err => {console.log(err)})

// get請求
axios.get(url)
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });

// post請求
axios.post(‘/user’, {
    name: 'Jerry',
    lastName: 'Liang'
  })
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });

 特殊場景的處理

  在開發過程中,經常會遇到比較尷尬的場景就是多請求的串行與并發,并發比較容易解決,不存在回調地獄,但是代碼可讀性就會容易變得很渣,而串行問題對于前端是絕望的,最好的辦法是后端來做合并,如果后端不做這塊的處理,前端就必須來面對回調地獄。

  多請求串行

// ajax
$.ajax({
    url: '',
    data: '',
    success: function (data) {
       $.ajax({
            url: '',
            data: '',
            success: function (data) {
                $.ajax({
                    // 如此一層嵌套一層
                })
            }
        }) 
    }
})

//axios
axios.get(url)
.then(res => {
    return axios.get(url,{
         {name:result.name}
    });
}).then(res => {
    //如此一層層嵌套
});

  多請求并行

//ajax 通過計數器實現(雖然Jquery支持$.when的方式,但此處不做案例)
var num = 0;
function all(){
    num++;
    if(n>=3)console.log('三個請求全部完成');
}
$.ajax({
    url: '',
    data: '',
    success: function (data) {
       console.log("ajax請求1 完成");
       all();
    }
})
$.ajax({
    url: '',
    data: '',
    success: function (data) {
       console.log("ajax請求2 完成");
       all();
    }
})
$.ajax({
    url: '',
    data: '',
    success: function (data) {
       console.log("ajax請求3 完成");
       all();
    }
})

//axios
function getInfo() {
  return axios.get(url);
}
function getUser() {
  return axios.get(url);
}
axios.all([getInfo(), getUser()])
  .then(axios.spread(function (info, user) {
    // 兩個請求現在都執行完成
  }));

 如何選擇(個人理解,僅供參考)

  1. 首先可以肯定的是,如果你的代碼依舊是基于Jquery,那毫無疑問,ajax就是你最好的選擇。
  2. 如果你使用的是任意MVVM框架,建議無腦使用axios,fetch在實際項目使用中,需要各種的封裝和異常處理,并非開箱即用,而axios可以做到直接替換$.ajax。
  3. 如果就是要使用fetch,那相信你也一定能封裝成自己的一套最佳實踐。
QQ群:WEB開發者官方群(515171538),驗證消息:10000
微信群:加小編微信 849023636 邀請您加入,驗證消息:10000
提示:更多精彩內容關注微信公眾號:全棧開發者中心(fsder-com)
網友評論(共0條評論) 正在載入評論......
理智評論文明上網,拒絕惡意謾罵 發表評論 / 共0條評論
登錄會員中心
福建时时结果查询