天天看點

【JavaScript】從AJAX到Fetch、axios

目錄

  • ​​1. AJAX​​
  • ​​1.1 簡介​​
  • ​​1.2 特點​​
  • ​​1.3 常見狀态碼​​
  • ​​1.4 使用方法​​
  • ​​1.5 使用Promise封裝AJAX​​
  • ​​2. Fetch​​
  • ​​2.1 Fetch簡介​​
  • ​​2.2 常用參數​​
  • ​​2.3 基本用法​​
  • ​​2.4 響應結果​​
  • ​​2.5 特點​​
  • ​​3. axios​​
  • ​​3.1 axios簡介​​
  • ​​3.2 基本用法​​
  • ​​3.3 響應結果​​
  • ​​3.4 全局配置​​
  • ​​3.5 攔截器​​
  • ​​4. async / await​​

前言:

在前後端互動的過程中,有很多資料請求的方式,例如AJAX、Fetch、axios等等,下面就一一來簡單列舉一下。

我們先來看一下URL的兩種的形式:

  1. 傳統的URL格式如下:
scheme://host:port/path?query#fragment      

其中:

scheme: 表示協定,如Http, Https, Ftp等;
host: 表示所通路資源所在的主機名:如:www.baidu.com;
port: 表示端口号,預設為80;
path: 表示所通路的資源在目标主機上的儲存路徑;
query: 表示查詢條件;
fragment:表示錨點(哈希),用于定位頁面的某個位置。

例如: http://www.baidu.com/search?words=Baidu      
  1. restful形式的URL

(1)HTTP的請求方式:

  • GET 查詢
  • POST 添加
  • PUT 修改
  • DELETE 删除

(2)符合規則的URL:(送出方式不同)

http://www.hello.com/books  GET
http://www.hello.com/books  POST
http://www.hello.com/books/123  PUT(對id為123的資料進行修改)
http://www.hello.com/books/123  DELETE(對id為123的資料進行删除)      

1. AJAX

1.1 簡介

AJAX 是 Asynchronous JavaScript and XML 的縮寫,指的是通過 JavaScript 的異步通信,從伺服器擷取 XML 文檔從中提取資料,再更新目前網頁的對應部分,而不用重新整理整個網頁。

1.2 特點

  1. 優點
  • 不需要插件支援(一般浏覽器且預設開啟 JavaScript 即可)
  • 使用者體驗極佳(不重新整理頁面即可擷取可更新的資料)
  • 提升 Web 程式的性能(在傳遞資料方面做到按需發送,不必整體送出)
  • 減輕伺服器和帶寬的負擔(将伺服器的一些操作轉移到用戶端)
  1. 缺點
  • 前進、後退的功能被破壞(因為 AJAX 永遠在目前頁,不會記錄前後頁面)
  • 搜尋引擎的支援度不夠(因為搜尋引擎爬蟲還不能了解 JS 引起變化資料的内容)

1.3 常見狀态碼

100 ~ 199 表示連接配接繼續
200 ~ 299 表示各種意義上的成功
300 ~ 399 表示重定向
400 ~ 499 表示各種用戶端錯誤
500 ~ 599      

1.4 使用方法

AJAX 包括以下幾個步驟:

  1. 建立XMLHttpRequest對象,也就是建立一個異步調用對象
  2. 建立一個新的HTTP請求,并指定其請求的方法、URL及驗證資訊
  3. 設定響應 HTTP 請求狀态變化的函數
  4. 發送 HTTP 請求
  5. 擷取異步調用傳回的資料
  6. 使用 JavaScript 和 DOM 實作局部重新整理
//原生AJAx
    var request = new XMLHttpRequest(); // 建立XMLHttpRequest對象;
    request.onreadystatechange = function () { // 狀态發生變化時,函數被回調;
        if (request.readyState === 4) { // 成功完成
            // 判斷響應結果:
            if (request.status === 200) {
                // 成功,通過responseText拿到響應的文本:
            } else {
                // 失敗,根據響應碼判斷失敗原因:
            }
        } else {
            // HTTP請求還在繼續...
        }
    }
    // 發送請求:
    request.open("POST","/skill-ajax/a/login",true);
    request.setRequestHeader("Content-type","application/x-www-form-urlencoded");
    request.send();
    alert('請求已發送,請等待響應...');

  // readyState值說明
  // 0,初始化,XHR對象已經建立,還未執行open
  // 1,載入,已經調用open方法,但是還沒發送請求
  // 2,載入完成,請求已經發送完成
  // 3,互動,可以接收到部分資料

  // status值說明
  // 200:成功
  // 404:沒有發現檔案、查詢或URl
  // 500:伺服器産生内部錯誤      

使用jQuery進行AJAX請求:

//jQuery中的AJAX
$.ajax({
    method: 'GET', // 1.9.0本版前用'type'
    url: url,
    data: data,
    dataType: dataType,
    success: function() {
       console.log('執行成功');
    },
    error: function() {
       console.log('執行出錯');
    }
})      

使用jQuery進行AJAX請求時它具有以下特點:

(1)優點:

  • 對原生XHR的封裝,做了相容處理,簡化了使用
  • 增加了對JSONP的支援,可以簡單處理部分跨域

(2)缺點:

  • 如果有多個請求,并且有依賴關系的話,容易形成回調地獄
  • 本身是針對MVC的程式設計,不符合現在前端MVVM的浪潮
  • ajax是jQuery中的一個方法。如果隻是要使用ajax卻要引入整個jQuery,很不合理

1.5 使用Promise封裝AJAX

這裡不多做介紹,之前寫了一篇相關文章:​​利用Promise封裝Ajax中get和post方法​​

2. Fetch

2.1 Fetch簡介

Fetch是基于Promise實作的,支援 async/await,它有更加簡單的資料擷取方式,功能更加強大、更靈活,可以看做是xhr的更新版。

// 原生XHR
var xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.onreadystatechange = function() {
    if (xhr.readyState === 4 && xhr.status === 200) {
        console.log(xhr.responseText)   // 從伺服器擷取資料
    }
}
xhr.send()

// fetch
fetch(url)
    .then(response => {
            return response.json();
    })
    .then(data => console.log(data)) // 這裡得到的才是真正的資料
    .catch(error => console.log(error))      

2.2 常用參數

常用的參數配置:

(1)​​

​method​

​​(String): HTTP請求方法,預設為GET (GET、POST、PUT、DELETE)

(2)​​

​body​

​​(String): HTTP的請求參數

(3)​​

​headers​

​(Object): HTTP的請求頭,預設為{}

2.3 基本用法

  1. GET 請求方式
//使用普通URL進行傳遞參數
fetch('/abc?id=123')
    .then(response => {
            return response.json();
    })
    .then(data => console.log(data)) 
    .catch(error => console.log(error))
    
// 使用restful形式進行傳參
fetch('/abc/123',{
       method:'get'
    }).then(response => {
            return response.json();
    }).then(data => console.log(data)) 
    .catch(error => console.log(error))      
  1. DELETE請求方式

delete請求方式和get方式類似:

//使用普通URL進行傳遞參數
fetch('/abc?id=123',{
     method:'delete'
  }).then(response => {
            return response.json();
  }).then(data => console.log(data)) 
    .catch(error => console.log(error))
    
// 使用restful形式進行傳參
fetch('/abc/123',{
       method:'delete'
    }).then(response => {
            return response.json();
    }).then(data => console.log(data)) 
    .catch(error => console.log(error))      
  1. POST請求方式
//以普通參數形式請求
fetch('/abc',{
     method:'post',
     body:'uname=zhangsan&psw=123',
     headers:{
        'Content-Type' : 'application/X-www-form-urlencoded'
     }
  }).then(response => {
            return response.json();
  }).then(data => console.log(data)) 
    .catch(error => console.log(error))

// 以json格式進行請求
 fetch('/abc',{
     method:'post',
     body:JSON.stringify({
         uname:'zhangsan',
         psw:'123'
     })    
     headers:{
        'Content-Type' : 'application/json'
     }
  }).then(response => {
            return response.json();
  }).then(data => console.log(data)) 
    .catch(error => console.log(error))      
  1. PUT請求方式

put請求方式和post類似:

//以普通參數形式請求
fetch('/abc/123',{   //123要修改資料的id
     method:'put',
     body:'uname=zhangsan&psw=123',
     headers:{
        'Content-Type' : 'application/X-www-form-urlencoded'
     }
  }).then(response => {
            return response.json();
  }).then(data => console.log(data)) 
    .catch(error => console.log(error))

// 以json格式進行請求
 fetch('/abc/123',{
     method:'put',
     body:JSON.stringify({
         uname:'zhangsan',
         psw:'123'
     })    
     headers:{
        'Content-Type' : 'application/json'
     }
  }).then(response => {
            return response.json();
  }).then(data => console.log(data)) 
    .catch(error => console.log(error))      

2.4 響應結果

Fetch響應資料的格式主要有以下兩種:

  • ​text()​

    ​:将傳回體處理成字元串類型
  • ​json()​

    ​​:傳回結果和​

    ​JSON.parse​

    ​(responseText)一樣

我們上面使用的是​

​json()​

​​格式,如果想用​

​text()​

​格式,直接替換即可。

2.5 特點

(1)優點:

在配置中,添加​

​mode:'no-cors'​

​就可以跨域了

fetch('/users.json', {
    method: 'post', 
    mode: 'no-cors',
    data: {}
}).then(function() { /* handle response */ });      

(2)缺點:

  • fetch隻對網絡請求報錯,對400,500都當做成功的請求,需要封裝去處理
  • fetch預設不會帶cookie,需要添加配置項。
  • fetch不支援abort,不支援逾時控制,使用setTimeout及Promise.reject的實作逾時控制并不能阻止請求過程繼續在背景運作,造成了流量的浪費。
  • fetch沒有辦法原生監測請求的進度,而XHR可以。

3. axios

3.1 axios簡介

axios是一個基于​

​promise​

​​的HTTP庫,可以用在浏覽器和 ​

​node.js​

​​ 中。它本質也是對原生​

​XMLHttpRequest​

​​的封裝,隻不過它是​

​Promise​

​的實作版本,符合最新的ES規範。

Vue作者尤雨溪推薦使用axios進行資料請求。

axios具有以下特點:

  • 支援浏覽器和 node.js
  • 支援 promise
  • 能攔截請求和響應
  • 自動轉換JSON資料
  • 提供了并發請求的接口

3.2 基本用法

  1. GET請求和DELETE請求

get請求和delete請求的用法類似,下面隻寫get請求:

//通過傳統的URL位址傳遞參數
axios.get('/user?id=12345')
  .then(function (response) {
    console.log(response);      // 這是傳回的一個封裝好的對象
    console.log(response.data); // 這才是背景響應的真正的資料
  })
  .catch(function (error) {
    console.log(error);
  });
  
//通過restful形式的URL進行傳參
axios.get('/user/id=12345')
  .then(function (response) {
    console.log(response);      
    console.log(response.data); 
  })
  .catch(function (error) {
    console.log(error);
  });
  
//通過params對象傳遞參數
axios.get('/user', {
    params: {
      ID: 12345
    }
  })
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });      
  1. POST請求和PUT請求

post和put類似,這裡隻列舉post請求方式:

// 通過預設選項傳參(預設傳遞的是json形式的資料)
axios.post('/user', {
     uname:'zhangsan',
     psw:'123'
  })
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });

//通過URLSearchParams傳遞參數(application/x-www-form-urlencoded)

const params = new URLSeardhParams(); 
params . append('uname', 'zhangsan');
params . append ('psw', '123');

axios.post('/user', params)
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });      
  1. 并發請求
function getUserAccount(){
  return axios.get('/user/12345');
}
function getUserPermissions(){
  return axios.get('/user/12345/permissions');
}
axios.all([getUserAccount(),getUserPermissions()])
  .then(axios.spread(function(acct,perms){
    //當這兩個請求都完成的時候會觸發這個函數,兩個參數分别代表傳回的結果
  }))      

3.3 響應結果

我們上文中隻說了響應的資料​

​response.data​

​,響應結果中還有以下主要屬性:

  • ​data​

    ​: 實際響應回來的資料
  • ​headers​

    ​ : 響應頭資訊
  • ​status​

    ​ : 響應狀态碼
  • ​statusText​

    ​ : 響應狀态資訊

3.4 全局配置

在發送請求之前,我們可以對axios請求設定全局配置:

// 逾時時間
axios.defaults.timeout = 3000; 
//設定預設位址,配置請求的基準URL位址,在請求時就可以不寫這一部分
axios.defaults.baseURL =http://www.baidu.com'; 
// 設定請求頭
axios.defaults.headers[ 'mytoken'] = 'helloworld'      

3.5 攔截器

  1. 請求攔截器

請求攔截器的作用是在送出請求之前設定一些資訊:

axios.interceptors.request.use(function(config){
     //在請求發出之前進行資訊設定
     config.headers.mytoken = 'helloworld'  // 和全局配置設定請求頭效果一樣,但是更加靈活
     return config;
   },function(error){
     // 處理響應的錯誤資訊
     console.log(error);
   });      
  1. 響應攔截器

響應攔截器的作用是在擷取資料之前對資料進行一些加工處理:

axios.interceptors.response.use(function(response){
     //對傳回的資料進行處理
      var data = response.data;
      return data; 
   },function(error){
     //處理響應的錯誤資訊
     console.log(error);
   });      

4. async / await

​async / await​

​方法是ES7中引入的新文法,可以更加便捷的進行異步操作。其中:

  • ​async​

    ​​關鍵字用于函數上(​

    ​async​

    ​函數的傳回值是Promise執行個體對象)
  • ​await​

    ​​關鍵字用于async函數當中(​

    ​await​

    ​可以得到異步的結果)
async function queryData (id) {
     const ret = await axios.get('/data'); //可以直接得到調用結果,不需要再使用then  
     return ret;
  }
  // 因為上一步傳回的Promise對象,是以通過調用then,可以直接獲得上面擷取到的資料
  queryData.then (ret=> { 
  console.log (ret)   
})      

使用​

​async / await​

​ 處理多個異步請求:

async function queryData(id) {
    const info = await axios. get('/async1') ;
    const ret = await axios . get ( 'async2?info='+info.data) ;
    return ret;
 }
 queryData.then (ret=>{
 console.log (ret)
 })      

繼續閱讀