如何使用axios發出高大上的HTTP請求

Da發表於2020-03-08

翻譯:Da
原文地址:blog.logrocket.com/how-to-make…

對前端工程師來說,跟伺服器交流的最通用方式就是Http協議,我們比較熟悉的傳送請求的方式有Fetch API和XMLHttpRequest。下面我們會全面的介紹Axios —— 一個基於瀏覽器內建的XMLHttpRequest介面的HTTP API庫,看看是哪些優秀的功能讓它在前端開發者中越來越流行。

選擇Axios的原因

跟Fetch一樣,Axios也是基於Promise的。但是,它提供了更強大,更靈活的特性配置。以下是相對於原生Fetch API的優點。

  • 可以攔截請求和響應
  • 簡化錯誤處理
  • XSRF防禦
  • 支援上傳進度
  • 支援響應超時
  • 支援請求取消
  • 支援舊版本瀏覽器
  • 自動轉換JSON資料

安裝

你可以使用以下方法安裝

  • npm:
$ npm install axios
複製程式碼
  • bower:
$ bower install axios
複製程式碼
  • 引入指令碼
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
複製程式碼

傳送請求

在axios中,傳送請求是非常簡單的,只需要將配置物件傳給Axios函式即可,url屬性是必填的;method預設為get。下面來看一個簡單的例子

// send a POST request
axios({
  method: 'post',
  url: '/login',
  data: {
    firstName: 'Finn',
    lastName: 'Williams'
  }
});
複製程式碼

用過JQuery的同學應該看著挺眼熟的,它的用法很像$.ajax。上面的程式碼實現了傳送Post請求到/login,並攜帶一個物件作為引數,Axios會自動將引數轉換為JSON格式,將其作為請求正文傳送。

方法速記

Axios同樣提供了一系列的速記方法,用來執行不同型別的請求。

  • axios.request(config)
  • axios.get(url[, config])
  • axios.delete(url[, config])
  • axios.head(url[, config])
  • axios.options(url[, config])
  • axios.post(url[, data[, config]])
  • axios.put(url[, data[, config]])
  • axios.patch(url[, data[, config]])

舉例如下,以下程式碼展示了前面的例子怎麼用axios.post重寫:

axios.post('/login', {
  firstName: 'Finn',
  lastName: 'Williams'
});
複製程式碼

處理響應

一旦HTTP請求發起,Axios就會返回一個Promise物件(fulfilled或rejected,取決於後端服務的響應),我們可以使用then()處理返回的結果,如下:

axios.post('/login', {
  firstName: 'Finn',
  lastName: 'Williams'
})
.then((response) => {
  console.log(response);
}, (error) => {
  console.log(error);
});
複製程式碼

如果返回的promise是fulfilled的,那麼作為then()第一個引數的函式將會被執行;若promise是rejected的,作為第二個引數的函式會被執行。根據文件所述,fulfilled狀態的value包含以下內容:

{
  // `data` is the response that was provided by the server
  data: {},
 
  // `status` is the HTTP status code from the server response
  status: 200,
 
  // `statusText` is the HTTP status message from the server response
  statusText: 'OK',
 
  // `headers` the headers that the server responded with
  // All header names are lower cased
  headers: {},
 
  // `config` is the config that was provided to `axios` for the request
  config: {},
 
  // `request` is the request that generated this response
  // It is the last ClientRequest instance in node.js (in redirects)
  // and an XMLHttpRequest instance the browser
  request: {}
}
複製程式碼

下面我們以向一個GitHub API傳送請求為例,看看它的返回值:

axios.get('https://api.github.com/users/mapbox')
  .then((response) => {
    console.log(response.data);
    console.log(response.status);
    console.log(response.statusText);
    console.log(response.headers);
    console.log(response.config);
  });

// logs:
// => {login: "mapbox", id: 600935, node_id: "MDEyOk9yZ2FuaXphdGlvbjYwMDkzNQ==", avatar_url: "https://avatars1.githubusercontent.com/u/600935?v=4", gravatar_id: "", …}
// => 200
// => OK
// => {x-ratelimit-limit: "60", x-github-media-type: "github.v3", x-ratelimit-remaining: "60", last-modified: "Wed, 01 Aug 2018 02:50:03 GMT", etag: "W/"3062389570cc468e0b474db27046e8c9"", …}
// => {adapter: ƒ, transformRequest: {…}, transformResponse: {…}, timeout: 0, xsrfCookieName: "XSRF-TOKEN", …}
複製程式碼

同時傳送請求

Axios有一個非常有趣的功能,他可以平行傳送多個請求,通過向axios.all()方法傳遞陣列格式的引數。這個方法會返回一個promise物件,並且當所有請求都被resolve時,它才會resolve。下面是個簡單的例子:

// execute simultaneous requests 
axios.all([
  axios.get('https://api.github.com/users/mapbox'),
  axios.get('https://api.github.com/users/phantomjs')
])
.then(responseArr => {
  //this will be executed only when all requests are complete
  console.log('Date created: ', responseArr[0].data.created_at);
  console.log('Date created: ', responseArr[1].data.created_at);
});

// logs:
// => Date created:  2011-02-04T19:02:13Z
// => Date created:  2017-04-03T17:25:46Z****
複製程式碼

以上程式碼向GitHub API傳送了兩個請求,然後列印了每個返回值的create_at屬性的值。需要注意的是:如果任何一個請求的被rejected,那麼該promise物件將會立即reject出第一個被reject的promise物件的結果。

為了方便,Axios同樣提供了一個axios.spread()方法,分配響應陣列的屬性給單獨的變數,下面是簡單的使用方法:

axios.all([
  axios.get('https://api.github.com/users/mapbox'),
  axios.get('https://api.github.com/users/phantomjs')
])
.then(axios.spread((user1, user2) => {
  console.log('Date created: ', user1.data.created_at);
  console.log('Date created: ', user2.data.created_at);
}));
複製程式碼

這段程式碼的返回值跟上段程式碼相同,唯一的不同就是axios.spread()方法將響應陣列中的值分配給兩個單獨的變數了。

傳送自定義的請求頭

用Axios自定義請求頭非常簡單,只需要簡單傳遞一個配置了請求頭的物件作為最後一個引數即可,如下:

const options = {
  headers: {'X-Custom-Header': 'value'}
};

axios.post('/save', { a: 10 }, options);
複製程式碼

轉換請求和響應的格式

預設情況下,Axios自動將請求和響應的格式轉換成JSON,但是它也允許你覆蓋預設行為,重寫定義不同的轉化機制。當API只接受特殊的資料格式,像XML或CSV時,這個功能就非常有用了。

在向伺服器傳送請求前,在config物件中設定transformRequest屬性(注意:這個方法只在PUT,POST,PATCH請求中生效),下面是使用方法:

const options = {
  method: 'post',
  url: '/login',
  data: {
    firstName: 'Finn',
    lastName: 'Williams'
  },
  transformRequest: [(data, headers) => {
    // transform the data

    return data;
  }]
};

// send the request
axios(options);
複製程式碼

想要在觸發then()或catch()之前修改響應資料的格式,你只需要設定transformResponse屬性,如下:

const options = {
  method: 'post',
  url: '/login',
  data: {
    firstName: 'Finn',
    lastName: 'Williams'
  },
  transformResponse: [(data) => {
    // transform the response

    return data;
  }]
};

// send the request
axios(options);
複製程式碼

攔截請求和響應

攔截HTTP請求是Axios很受歡迎的一個特性,通過這個特性,你可以在自己的應用程式向伺服器傳送請求之前檢查、修改請求(反之亦然),這個方法對於各種隱性的任務(像日誌或者身份驗證)非常有用。

一眼看過去,攔截器的功能很像一個轉換器,但是他們之間有一個非常重要的不同點:轉化器只將資料和頭資訊作為引數接受,攔截器則是接收整個響應物件或請求配置。

你可以用以下方式宣告一個axios攔截器:

// declare a request interceptor
axios.interceptors.request.use(config => {
  // perform a task before the request is sent
  console.log('Request was sent');

  return config;
}, error => {
  // handle the error
  return Promise.reject(error);
});

// sent a GET request
axios.get('https://api.github.com/users/mapbox')
  .then(response => {
    console.log(response.data.created_at);
  });
複製程式碼

以上程式碼會列印每當傳送這個請求時,控制檯都會列印上面"Request was sent",然後等待,直到伺服器返回響應,此時,就會列印這個賬號在GitHub上的建立時間(response.data.created_at)。使用攔截器後,你就不用再給每個HTTP請求單獨的寫一段重複的程式碼了。

Axios同樣提供了響應的攔截器,讓我們在伺服器嚮應用返回響應時,統一轉換返回值:

// declare a response interceptor
axios.interceptors.response.use((response) => {
  // do something with the response data
  console.log('Response was received');

  return response;
}, error => {
  // handle the response error
  return Promise.reject(error);
});

// sent a GET request
axios.get('https://api.github.com/users/mapbox')
  .then(response => {
    console.log(response.data.created_at);
  });
複製程式碼

客戶端支援XSRF防禦

Cross-site request forgery (簡稱XSRF,跨站請求偽造)是一種攻擊網路託管應用程式的方法,攻擊者偽裝成合法且受信任的使用者,以影響該應用程式與使用者瀏覽器之間的互動。有很多方法可以執行這種攻擊,包括XMLHttpRequest

幸好,Axios通過允許使用者在發出請求時嵌入額外的認證資訊的方式防禦XSRF,這使伺服器能夠發現來自未授權地址的請求。以下是使用方法:

const options = {
  method: 'post',
  url: '/login',
  xsrfCookieName: 'XSRF-TOKEN',
  xsrfHeaderName: 'X-XSRF-TOKEN',
};

// send the request
axios(options);
複製程式碼

監控POST請求進度

Axios另一個NB的特性是,他可以監控請求的進度。這個功能在我們下載或上傳大檔案時非常有用。Axios文件上提供了例子,但是簡單起見,我們在本教程中使用Axios Progress Bar模組。

首先,我們需要引入相關的指令碼和樣式

<link rel="stylesheet" type="text/css" href="https://cdn.rawgit.com/rikmms/progress-bar-4-axios/0a3acf92/dist/nprogress.css" />

<script src="https://cdn.rawgit.com/rikmms/progress-bar-4-axios/0a3acf92/dist/index.js"></script>
複製程式碼

然後我們就可以像下面這樣使用進度條啦:

loadProgressBar()

const url = 'https://media.giphy.com/media/C6JQPEUsZUyVq/giphy.gif';

function downloadFile(url) {
  axios.get(url)
  .then(response => {
    console.log(response)
  })
  .catch(error => {
    console.log(error)
  })
}

downloadFile(url);
複製程式碼

我們可以這樣覆蓋預設樣式:

#nprogress .bar {
    background: red !important;
}

#nprogress .peg {
    box-shadow: 0 0 10px red, 0 0 5px red !important;
}

#nprogress .spinner-icon {
    border-top-color: red !important;
    border-left-color: red !important;
}
複製程式碼

取消請求

有些情況下,你可能不關心請求的結果,並要取消已經傳送的請求,這也是可以實現的哦,只需要使用cancelToken。注意,取消請求的功能是在1.5版本新增的,並且基於可取消的promise的提案,下面是使用方法:

const source = axios.CancelToken.source();

axios.get('https://media.giphy.com/media/C6JQPEUsZUyVq/giphy.gif', {
  cancelToken: source.token
}).catch(thrown => {
  if (axios.isCancel(thrown)) {
    console.log(thrown.message);
  } else {
    // handle error
  }
});

// cancel the request (the message parameter is optional)
source.cancel('Request canceled.');
複製程式碼

您還可以通過傳遞執行器函式給CancelToken建構函式來建立CancelToken,如下所示:

onst CancelToken = axios.CancelToken;
let cancel;

axios.get('https://media.giphy.com/media/C6JQPEUsZUyVq/giphy.gif', {
  // specify a cancel token
  cancelToken: new CancelToken(c => {
    // this function will receive a cancel function as a parameter
    cancel = c;
  })
}).catch(thrown => {
  if (axios.isCancel(thrown)) {
    console.log(thrown.message);
  } else {
    // handle error
  }
});

// cancel the request
cancel('Request canceled.');
複製程式碼

瀏覽器相容

Axios在瀏覽器相容上是非常有優勢的,即使是IE11也可以很好地相容。

Chrome Firefox Safari Edge IE
11

結語

在這篇文章中,我們學習了Axios大部分主要的特性,以及他們的使用方法。還有一些文章中沒涉及的內容,感興趣的同學就去官方文件中深入瞭解吧!

相關文章