Battle!用JavaScript發(fā)出HTTP請(qǐng)求的不同方法
本文轉(zhuǎn)載自公眾號(hào)“讀芯術(shù)”(ID:AI_Discovery)
使用JavaScript時(shí),總會(huì)有各種需要發(fā)出調(diào)用請(qǐng)求的情況,進(jìn)行ajax調(diào)用什么技術(shù)更適合呢?
最初,盡管有一些方法可以在不刷新頁面的情況下從服務(wù)器提取數(shù)據(jù),但它們通常依賴于笨拙的技術(shù)。直到微軟為Outlook電子郵件客戶端的替代瀏覽器開發(fā)了XMLHttpRequest。它在2006年成為了Web標(biāo)準(zhǔn)。
2015年,F(xiàn)etch API隨ES6引入。通用的Request和Response接口提供了一致性,而Promises允許更容易的鏈接和沒有回調(diào)的異步/等待。Fetch簡潔,優(yōu)雅且易于理解,但是還有其他不錯(cuò)的選擇,本文將簡要的含義、語法以及利弊。
以下代碼展示了使用不同替代方法的基本HTTP GET和POST示例。現(xiàn)在開始吧~
XMLHttpRequest
XMLHttpRequest對(duì)象可用于從Web服務(wù)器請(qǐng)求數(shù)據(jù)。它是這次比較中最早的方法,盡管其他選擇都優(yōu)于它,但由于其向后兼容性和成熟度,它仍然有效且有用。
得到:
- var req= new XMLHttpRequest();//The onreadystatechange property
- //specifies a function to be
- //executed every time the status
- //of the XMLHttpRequest changes
- req.onreadystatechange = function() {
- if (this.readyState == 4 &&this.status == 200) {
- //The responseText property
- //returns a text string
- console.log(xhttp.responseText)
- //Do some stuff
- }
- };req.open("GET", "http://dataserver/users", true);
- req.send();
發(fā)送:
- varformData = new FormData();
- formData.append("name", "Murdock");
- var req = new XMLHttpRequest();
- req.open("POST", "http://dataserver/update");
- req.send(formData);
優(yōu)點(diǎn):
- 不需要從外部源加載
- 向后兼容性
- 成熟/穩(wěn)定
- 在所有瀏覽器中均可使用
- 是原生瀏覽器API
缺點(diǎn):
- 支持回調(diào)地獄
- 笨拙冗長的語法
- Fetch能自然地替代它
Qwest
Qwest是一個(gè)基于Promise的簡單ajax庫,它支持XmlHttpRequest2的獨(dú)立數(shù)據(jù),例如ArrayBuffer,Blob和FormData。
得到:
- qwest.get('http://dataserver/data.json')
- .then(function(xhr, response) {
- // ...do some stuff whith data
- });
發(fā)送:
- qwest.post('http://dataserver/update',{
- firstname: 'Murdock',
- age: 30
- })
- .then(function(xhr, response) {
- // Make some useful actions
- })
- .catch(function(e, xhr, response) {
- // Process the error
- });
優(yōu)點(diǎn):
- 可以建立請(qǐng)求限制
- 基于Promise
缺點(diǎn):
- 并非所有瀏覽器上都可使用XmlHttpRequest2
- 非原生
- 必須從外部源加載
JQuery.ajax
該庫在不久前被廣泛用于發(fā)出HTTP異步請(qǐng)求。jQuery的所有Ajax方法都返回XMLHTTPRequest對(duì)象的超集
得到:
- $.ajax({
- url: 'http://dataserver/data.json'
- }).done(function(data) {
- // ...do some stuff whith data
- }).fail(function() {
- // Handle error
- });
發(fā)送:
- $.ajax({
- type: "POST",
- url: 'http://dataserver/update',
- data: data,
- success: successCallBack,
- error: errorCallBack,
- dataType: dataType
- });
優(yōu)點(diǎn):
- 良好的支持和文檔
- 可配置的對(duì)象
- 在許多項(xiàng)目中使用
- 學(xué)習(xí)曲線低
- 它返回XMLHttpRequest對(duì)象,因此可以中止請(qǐng)求
缺點(diǎn):
- 非原生
- 必須從外部源加載
- 沒有與Promises結(jié)合
- 對(duì)于原生ES6 Fetch不是必需的。
Axios
基于Promise的HTTP庫,用于在瀏覽器和Nodejs上執(zhí)行HTTP請(qǐng)求。
得到:
- axios({
- url: 'http://dataserver/data.json',
- method: 'get'
- })
發(fā)送:
- axios.post('http://dataserver/update',{
- name: 'Murdock'
- })
- .then(function (response) {
- console.log(response);
- })
- .catch(function (error) {
- console.log(error);
- });
優(yōu)點(diǎn):
- 使用promise避免回調(diào)地獄
- 在瀏覽器和Nodejs上均可使用
- 支持上傳進(jìn)度
- 可以設(shè)置響應(yīng)超時(shí)
- 通過簡單地向其傳遞配置對(duì)象即可配置請(qǐng)求
- Axios已實(shí)現(xiàn)可撤銷的promise提議
- 自動(dòng)將數(shù)據(jù)轉(zhuǎn)換為JSON
缺點(diǎn):
- 非原生
- 必須從外部源加載
SuperAgent
SuperAgent是ajax API,旨在提供靈活性,可讀性和較低的學(xué)習(xí)曲線。它也可以與Node.js一起使用。
得到:
- request('GET','http://dataserver/data.json').then(
- success, failure);
.query()方法接受對(duì)象,這些對(duì)象與GET方法一起使用時(shí)將形成查詢字符串。以下代碼將產(chǎn)生路徑/ dataserver / search?name = Manny&lastName = Peck&order = desc。
- request
- .get('/dataserver/search')
- .query({ name: 'Templeton' })
- .query({ lastname: 'Peck' })
- .query({ order: 'desc' })
- .then(res => {console.dir(res)}
- });
發(fā)送:
- request
- .post('http://dataserver/update')
- .send({ name: 'Murdock' })
- .set('Accept', 'application/json')
- .then(res => {
- console.log('result' +JSON.stringify(res.body));
- });
優(yōu)點(diǎn):
- 基于Promise
- 在Node.js和瀏覽器中均可使用
- 可以調(diào)用request.abort()方法中止請(qǐng)求
- 社區(qū)的知名庫
- 發(fā)出HTTP請(qǐng)求的無縫接口
- 出現(xiàn)故障時(shí)支持重試請(qǐng)求
缺點(diǎn):
- 它不支持以XMLHttpRequest的形式監(jiān)視加載進(jìn)度
- 非原生
- 必須從外部源加載
Http-client
Http-client允許使用JavaScript的訪存API組成HTTP客戶端。
得到:
- //usingES6 modules
- import { createFetch, base, accept, parse } from 'http-client'const fetch =createFetch(
- base('http://dataserver/data.json'),
- accept('application/json'),
- parse('json')
- )fetch('http://dataserver/data.json').then(response => {
- console.log(response.jsonData)
- })
發(fā)送:
- //usingES6 modules
- import { createFetch, method, params } from 'http-client'const fetch =createFetch(
- params({ name: 'Murdock' }),
- base('http://dataserver/update')
- )
優(yōu)點(diǎn):
- 在Node.js和瀏覽器中均可使用
- 由服務(wù)器端工作人員使用
- 基于Promise
- 提供頭部保護(hù)裝置,以提高CORS的安全性
缺點(diǎn):
- 必須從外部源加載
- 非原生
Fetch
Fetch是原生瀏覽器API,用于發(fā)出替代XMLHttpRequest的請(qǐng)求。與XMLHttpRequest相比,F(xiàn)etch使網(wǎng)絡(luò)請(qǐng)求更容易。Fetch API使用Promises避免XMLHttpRequest回調(diào)地獄。
得到:
- //WithES6 fetch
- fetch('http://dataserver/data.json')
- .then(data => {
- // ...do some stuff whith data
- }).catch(error => {
- // Handle error
- });
發(fā)送:
- fetch('http://dataserver/update',{
- method: 'post',
- headers: {
- 'Accept': 'application/json,text/plain, */*',
- 'Content-Type': 'application/json'
- },
- body: JSON.stringify({name: 'Murdock'})
- }).then(res=>res.json())
- .then(res => console.log(res));//ORwith ES2017 for example(async () => {
- const response = awaitfetch('http://dataserver/update', {
- method: 'POST',
- headers: {
- 'Accept': 'application/json',
- 'Content-Type': 'application/json'
- },
- body:JSON.stringify({name='Murdock'})
- });const result = awaitresponse.json();console.log(result);
- })();
優(yōu)點(diǎn):
- 是原生瀏覽器API
- Fetch基本上是經(jīng)過完善的XMLHttpRequest
- 友好且易于學(xué)習(xí)
- 與大多數(shù)最近使用的瀏覽器兼容
- 是原生XMLHttpRequest對(duì)象的自然替代
- 學(xué)習(xí)曲線低
- 不需要從外部源加載它
- 使用promises避免回調(diào)地獄
- 不需要更多依賴項(xiàng)
缺點(diǎn):
- 處理JSON數(shù)據(jù)的過程分為兩步。第一個(gè)是發(fā)出請(qǐng)求,然后第二個(gè)是在響應(yīng)時(shí)調(diào)用.json()方法。對(duì)于Axios,默認(rèn)情況下會(huì)收到JSON響應(yīng)。
- 從Fetch()返回的Promise僅在網(wǎng)絡(luò)故障或任何阻止請(qǐng)求完成的情況發(fā)生時(shí)拒絕。即使響應(yīng)為HTTP 404或500,也不會(huì)拒絕HTTP錯(cuò)誤狀態(tài)。
- 缺乏其他庫的一些有用功能,例如:取消請(qǐng)求。
- 默認(rèn)情況下,F(xiàn)etch不會(huì)從服務(wù)器發(fā)送或接收Cookie,如果站點(diǎn)依賴于維持用戶會(huì)話,則會(huì)導(dǎo)致未經(jīng)身份驗(yàn)證的請(qǐng)求。但是可以通過添加以下內(nèi)容來啟用:
- {credentials: “same-origin.”}
Fetch是一個(gè)新標(biāo)準(zhǔn),新版本的Chrome和Firefox無需使用任何其他庫就可支持它。
此外,Axios,SuperAgent或其他庫都有適合的文檔,易于使用,并且學(xué)習(xí)曲線不太高。在某些情況下,它們可以提供Fetch不具有的功能。
Fetch在JavaScript里是原生的,足以滿足項(xiàng)目需求。如果沒有特殊需求,我認(rèn)為Fetch就是最合適的選擇。