經常使用的三種請求方式ajax,axios,fetch

jQuery是一個快速、簡潔的JavaScript框架,是繼Prototype以後又一個優秀的JavaScript代碼庫(_或JavaScript框架_)。jQuery設計的宗旨是「write Less,Do More」,即倡導寫更少的代碼,作更多的事情。它封裝JavaScript經常使用的功能代碼,提供一種簡便的JavaScript設計模式,優化HTML文檔操做、事件處理、動畫設計和Ajax交互。做者我也是在2015年就開始用jQuery,那時候跟同事比看誰寫的代碼更短

如若看個jQuery源碼的同窗,j應該知道jq是對原生XHR的封裝,另外還增長了jsonp的支持,讓ajax請求能夠支持跨域請求,
可是要注意的是:jsonp請求本質不是XHR異步請求,就是請求了一個js文件,所以在瀏覽器的network面板中的xhr標籤下看不到jsonp的跨域請求,可是在js標籤下能看見,由於它利用src特性請求任何一個網站的資源。php

ajax常規用法

$.ajax({
    url: "https://www.api.com/api/xxx",  //ajax請求地址
    
    cache: true,// 默認true,dataType 爲 script 和 jsonp 時默認爲 false。設置爲 false 將不緩存此頁面
    
    type: "GET",//請求方式 "POST" 或 "GET", 默認爲 "GET"。注意:其它 HTTP 請求方法,如 PUT 和 DELETE 也可使用,但僅部分瀏覽器支持。
    
    dataType: "json",    //根據返回數據類型能夠有這些類型可選:xml html script json jsonp text
    
    timeout:Number //設置請求超時時間(毫秒), 此設置將覆蓋全局設置。
    
    //發送到服務器的數據,能夠直接傳對象{a:0,b:1},若是是get請求會自動拼接到url後面,如:&a=0&b=1
    //若是爲數組,jQuery 將自動爲不一樣值對應同一個名稱。如 {foo:["bar1", "bar2"]} 轉換爲 "&foo=bar1&foo=bar2"。
    data: {},
    
    //默認true設置下,全部請求均爲異步請求。若是須要發送同步請求,請將此選項設置爲 false。注意,同步請求將鎖住瀏覽器,用戶其它操做必須等待請求完成才能夠執行。
    async: true,
    
    //發送請求前可修改 XMLHttpRequest 對象的函數。
    //XMLHttpRequest 對象是惟一的參數。這是一個 Ajax 事件。
    //若是返回false能夠取消本次ajax請求,也能設置一些http協議的header頭信息。
    beforeSend:function(xhr){
        // 也能夠禁用按鈕防止重複提交
        $("#submit").attr({ disabled: "disabled" });
    },
    
    //context這個對象用於設置ajax相關回調函數的上下文。也就是說,讓回調函數內this指向這個對象(若是不設定這個參數,那麼this就指向調用本次AJAX請求時傳遞的options參數)。
    //好比指定一個DOM元素做爲context參數,這樣就設置了success回調函數的上下文爲這個DOM元素。
    context: document.body,
    
    //請求成功後的回調函數
    success: function(data,textStatus){
        //this 調用本次AJAX請求時傳遞的options參數 ,若是設置context來改變了this,那這裏的this就是改變過的
    },
    
    //請求失敗時調用此函數。有如下三個參數:XMLHttpRequest 對象、錯誤信息、(可選)捕獲的異常對象。
    //若是發生了錯誤,錯誤信息(第二個參數)除了獲得null以外,還多是"timeout", "error", "notmodified" 和 "parsererror"。
    error:function(XMLHttpRequest, textStatus, errorThrown){
        // 一般 textStatus 和 errorThrown 之中
        // 只有一個會包含信息
        // this 調用本次AJAX請求時傳遞的options參數
    },
    
    //請求完成後回調函數 (請求成功或失敗以後均調用)。參數: XMLHttpRequest 對象和一個描述成功請求類型的字符串
    complete:function(XMLHttpRequest, textStatus) {
        //this 調用本次AJAX請求時傳遞的options參數
    },
    
    //一組數值的HTTP代碼和函數對象,當響應時調用了相應的代碼。例如,若是響應狀態是404,將觸發如下警報:
    statusCode:{
        404:function(){
            alert('404,頁面不存在');
        }
    }
});

ajax.post

$.ajax({
    type: "POST",
    url: "https://www.api.com/api/xxx",
    dataType:'json',
    data: {id:1},//也能夠是字符串連接"id=1",建議用對象
    success: function(data){
        console.log("返回的數據: " + data );
    }
});
或者
$.post("https://www.api.com/api/xxx",{id:1},function(data){
    console.log("返回的數據: " + data );
},'json');

ajax.get

$.ajax({
    type: "GET",
    url: "https://www.api.com/api/xxx",
    dataType:'json',
    data: {id:1001},//也能夠是字符串連接"id=1001",建議用對象
    success: function(data){
        console.log("返回的數據: " + data );
    }
});
或者
$.get("https://www.api.com/api/xxx",{id:1},function(data){
    console.log("返回的數據: " + data );
},'json');

ajax.form

$("form").on("submit",function(){
    var url = this.action;   // 能夠直接取到表單的action
    var formData = $(this).serialize(); // 序列化表單數據
    $.post(url,formData,function(data){
        //返回成功,能夠作一個其餘事情
        console.log(data);
    },'json');
    //阻止表單默認提交行爲
    return false
})

ajax.done

ajax請求成功一般是使用回調的方式處理返回數據,其實jquery中也可使用連寫方式而不是回調的方式html

// 該參數能夠是一個函數或一個函數的數組。當延遲成功時,done中函數被調用,回調執行是依照他們添加的順序
$.get("https://www.api.com/api/xxx",{id:1}).done(function() {
    // 返回成功
}).fail(function(){
    // 處理失敗;
});

ajax.then

$.get("https://www.api.com/api/xxx",{id:1}).then( 
    function(){ 
        //返回成功
    }, 
    function(){ 
       // 處理失敗;
    }
);

ajax.when

兩個所有請求成功纔會執行回調, 不然就是失敗,相似於Promise.allvue

$.when($.ajax("p1.php"), $.ajax("p2.php"))
.then(
    function(){ 
        //兩個所有請求成功,才執行
    }, 
    function(){ 
        //任何一個執行失敗
    }
);

ajax.獲取文件

$.getScript():jQuery提供了此方法來直接加載js文件,與加載一個HTML片斷同樣簡單方便,而且不須要對JavaScript文件進行處理,JavaScript文件會自動執行node

$.getJSON('test.json', function(data)  {
    // 獲取文件成功的回調   
});

ajax.load

load() 方法經過 AJAX 請求從服務器加載數據,並把返回的數據放置到指定的元素中jquery

$('#result').load('ajax/test.html', function() {
    alert('Load was performed.');
});
//.load() 方法,與 $.get() 不一樣,容許咱們規定要插入的遠程文檔的某個部分。這一點是經過 url 參數的特殊語法實現的。若是該字符串中包含一個或多個空格,緊接第一個空格的字符串則是決定所加載內容的 jQuery 選擇器
// 若是test.html接口返回的是個html,則會插入到#container元素中
$('#result').load('ajax/test.html #container');

Axios

特性ios

  • 從瀏覽器中建立 XMLHttpRequest
  • 從 node.js 發出 http 請求
  • 支持 Promise API
  • 攔截請求和響應
  • 轉換請求和響應數據
  • 取消請求
  • 自動轉換JSON數據
  • 客戶端支持防止 CSRF/XSRF

APIgit

  • 全局github

    • axios.request(config)最終http請求都是執行這個方法
    • axios(config)和axios.request()等價
    • axios(url[, config])axios(config)快捷方式
    • axios.[METHODS](url, config)axios(config)快捷方式
  • 自定義實例ajax

    • axios.create(config)自定義配置,建立實例instance。調用方式和axios方法一致
  • 攔截器json

    • axios.interceptors.request.use
    • axios.interceptors.response.use

常見用法

配置優先級:lib/default.js中的庫默認值 -->實例的config屬性--> 請求的config參數
// 全局調用
   axios({
     method:'get',
     url:'https://www.api.com/api/xxx',
     field: 123
   }) // axios(config)
   axios('http://bit.ly/2mTM3nY', {field: 123}) // axios(url[, config])
   axios.get('http://bit.ly/2mTM3nY', {field: 123}) // axios.[METHODS](url, config)

   // 自定義實例調用
   const instance = axios.create({
     baseURL: 'https://www.api.com/api/xxx'
   });
   instance({
     method:'get',
     url:'2mTM3nY',
     field: 123
   }) // instance(config)
   instance.get('2mTM3nY', {field: 123}) // instance.[METHODS](url, config)

爲什麼axios有如此多使用方式

源碼在lib/default.js中

function createInstance(defaultConfig) {
      var context = new Axios(defaultConfig);
      // instance指向了request方法,且上下文指向context
      // instance(config) = Axios.prototype.request(config)
      var instance = bind(Axios.prototype.request, context);

      // 把Axios.prototype上的方法擴展到instance對象上
      // 這樣 instance 就有了 get、post、put等METHOD方法
      // 同時指定上下文爲context,這樣執行Axios原型鏈上的方法時,this會指向context
      utils.extend(instance, Axios.prototype, context);

      // 把context對象上的自身屬性和方法擴展到instance上
      utils.extend(instance, context);

      return instance;
    }

    // 導出時就建立一個默認實例,因此能夠經過axios(config)發出請求
    var axios = createInstance(defaults);
    axios.Axios = Axios;

    // 工廠模式建立axios實例,其實最終都是調用createInstance方法。
    // 因此實例調用方式和全局axios調用方式相同。instance(config) = axios(config)
    axios.create = function create(instanceConfig) {
      return createInstance(mergeConfig(axios.defaults, instanceConfig));
    };
    module.exports = axios;
    module.exports.default = axios; // 容許在ts中導入

重點是createInstance方法,該方法拿到一個Function,該Function指向請求入口Axios.prototype.request,而且該Function還繼承了Axios.prototype的每一個方法,而且上下文指向同一個對象context。axios包默認導出是該Function,而自定義實例axios.create是一個工廠模式,最終都調用createInstance方法。

總體流程

請求流程實質上無非就是輸入和輸出,輸入request config配置(如url、method、data等),輸出最終的response data數據。中間涉及到較多的數據預處理,如根據data數據類型(如JSON),設置Content-Type: json頭信息;再如根據響應的數據類型,默認轉換爲json格式。這些預處理須要axios庫自動完成,同時也要暴露出相關配置給開發者,以此實現開發者自定義預處理。

Axios經過攔截者(Interceptors)來實現上面說的數據預處理,具體經過使用chain鏈式來逐一插入處理邏輯。默認狀況下,先拿到這次請求的config配置,把config做爲參數,傳遞到dispatchRequest方法中,該方法會根據當前環境(Browser/Node)來調用不一樣的adapter發送請求,以此得到最終的response data。同時Axios還容許使用request/response Interceptors進行請求前和響應後的自定義處理,其實質是將預處理函數,插入chain數組中,再統一按照順序逐步執行預處理方法(Promise保證順序)。

Axios類是核心內容,該類request方法是全部請求的開始入口。源碼在lib/core/Axios.js:

Axios.prototype.request = function request(config) {
  // 1. 容許 axios('url'[, config]) = axios(config)
  if (typeof config === 'string') {
    config = arguments[1] || {};
    config.url = arguments[0];
  } else {
    config = config || {};
  }

  // 配置文件合併策略優先級
  config = mergeConfig(this.defaults, config);
  config.method = config.method ? config.method.toLowerCase() : 'get';

  // 2. 定義攔截器中間件鉤子
  // dispatchRequest是真正開始下發請求,執行config中設置的adapter方法
  var chain = [dispatchRequest, undefined];
  var promise = Promise.resolve(config);
  // 添加請求前鉤子
  this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
    chain.unshift(interceptor.fulfilled, interceptor.rejected);
  });
  // 添加請求後鉤子
  this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
    chain.push(interceptor.fulfilled, interceptor.rejected);
  });

  // 3. chain鏈關鍵代碼,promise鏈路傳遞下去
  while (chain.length) {
    promise = promise.then(chain.shift(), chain.shift());
  }

  return promise;
};

// 提供對request方法的METHOD快捷方式,實質都是調用Axios.prototype.request方法
// axios.get(url, config) = axios(config)
utils.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoData(method) {
  Axios.prototype[method] = function(url, config) {
    return this.request(utils.merge(config || {}, {
      method: method,
      url: url
    }));
  };
});

utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) {
  Axios.prototype[method] = function(url, data, config) {
    return this.request(utils.merge(config || {}, {
      method: method,
      url: url,
      data: data
    }));
  };
});

如何使用

請看我發表一篇《vue+axios+promise實際開發用法》,詳細介紹具體用法

fetch

Fetch API 是近年來被說起將要取代XHR的技術新標準,是一個 HTML5 的 API。
Fetch 並非XHR的升級版本,而是從一個全新的角度來思考的一種設計。Fetch 是基於 Promise 語法結構,並且它的設計足夠低階,這表示它能夠在實際需求中進行更多的彈性設計。對於XHR所提供的能力來講,Fetch 已經足夠取代XHR,而且提供了更多拓展的可能性。

基本用法

// 獲取 some.json 資源  
fetch('some.json')  
 .then(function(response) {  
    return response.json();  
 })  
 .then(function(data) {  
    console.log('data', data);  
 })  
 .catch(function(error) {  
    console.log('Fetch Error: ', error);  
 });  
  
// 採用ES2016的 async/await 語法  
async function() {  
 try {  
    const response = await fetch('some.json');  
    const data = response.json();  
    console.log('data', data);  
 } catch (error) {  
    console.log('Fetch Error: ', error)  
 }  
}

fetch.Post請求

fetch('https://www.api.com/api/xxx', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
    },
    body: 'a=1&b=2',
}).then(resp => resp.json()).then(resp => {
    console.log(resp)
});

fetch.Get請求

fetch('https://www.api.com/api/xxx?location=北京&key=bc08513d63c749aab3761f77d74fe820',{
    method:'GET'
}) // 返回一個Promise對象
.then((res)=>{
    return res.json();
})
.then((res)=>{
    console.log(res) // res是最終的結果
})

fetch請求網頁

fetch('https://www.api.com/api/xxx')
    .then(response => response.text())
    .then(data => console.log(data));

自定義header

var headers = new Headers({
    "Content-Type": "text/plain",
    "X-Custom-Header": "aaabbbccc",
});

var formData = new FormData();
formData.append('name', 'lxa');
formData.append('file', someFile);

var config = {
    credentials: 'include', // 支持cookie
    headers: headers, // 自定義頭部
    method: 'POST', // post方式請求
    body: formData // post請求攜帶的內容
};

fetch('https://www.api.com/api/xxx', config)
    .then(response => response.json())
    .then(data => console.log(data));
    
// 或者這樣添加頭部
var content = "Hello World";
var myHeaders = new Headers();
myHeaders.append("Content-Type", "text/plain");
myHeaders.append("Content-Length", content.length.toString());
myHeaders.append("X-Custom-Header", "ProcessThisImmediately");

fetch其餘參數

  • method: 請求的方法,例如:GET,POST
  • headers: 請求頭部信息,能夠是一個簡單的對象,也能夠是 Headers 類實例化的一個對象。
  • body: 須要發送的信息內容,能夠是Blob,BufferSource,FormData,URLSearchParams或者USVString。注意,GET,HEAD方法不能包含body。
  • mode: 請求模式,分別有cors,no-cors,same-origin,navigate這幾個可選值。

    • cors: 容許跨域,要求響應中Acess-Control-Allow-Origin這樣的頭部表示容許跨域。
    • no-cors: 只容許使用HEAD,GET,POST方法。
    • same-origin: 只容許同源請求,不然直接報錯。
    • navigate: 支持頁面導航。
  • credentials: 表示是否發送cookie,有三個選項

    • omit: 不發送cookie
    • same-origin: 僅在同源時發送cookie
    • include: 發送cookie
  • cache: 表示處理緩存的策略。
  • redirect: 表示發生重定向時,有三個選項

    • follow: 跟隨。
    • error: 發生錯誤。
    • manual: 須要用戶手動跟隨。
  • integrity: 包含一個用於驗證資資源完整性的字符串
var URL = 'https://www.api.com/api/xxx';  
// 實例化 Headers  
var headers = new Headers({  
    "Content-Type": "text/plain",  
    "Content-Length": content.length.toString(),  
    "X-Custom-Header": "ProcessThisImmediately",  
});  
var getReq = new Request(URL, {method: 'GET', headers: headers });  
fetch(getReq).then(function(response) {  
    return response.json();  
}).catch(function(error) {  
    console.log('Fetch Error: ', error);  
});

關於我

橫版二維碼.png

參考文章

ajax 的簡單實例以及高級用法
Axios用法與原理
瞭解 Fetch API
HTML5 fetch API

相關文章
相關標籤/搜索