原文:Comparing different ways to make HTTP requests in Javascript in 2020
翻译:码中人
最近我有个任务,在一个大型项目中选择用哪种方式发送ajax请求。
很早以前,虽然有一些方法将数据从一个服务器而不会刷新页面,但往往依赖于笨重的技术。后来,微软开发XMLHttpRequest技术,以便在浏览器上 Outlook电子邮件客户端可以不刷新整个页面,就能收到新的email,XMLHttpRequest在2006年成为一个web标准。
Fetch API是在2015年ES6标准中推出的。Fetch 请求和响应接口非常一致,支持promise、异步回调而不需要回调函数。Fetch API简洁优雅、容易理解,待会我们会进一步讨论。
总的来说,本文会对以下方式的优缺点进行讨论总结:
- XMLHttpRequest
- JQuery.ajax
- Qwest
- SuperAgent
- Http-client
- Axios
- Fetch
接下来会通过一些简单代码展示基本的HTTP GET和POST请求,让我们开始吧。
XMLHttpRequest
可以使用XMLHttpRequest对象从web服务器请求数据。这个方法比较老旧,虽然其它api写起来比较轻松,但它仍然是有效的和有用的,并且向后兼容。
GET
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();
POST
var formData = new FormData();
formData.append("name", "Murdock");
var req = new XMLHttpRequest();
req.open("POST", "http://dataserver/update");
req.send(formData);
优点
- 所有浏览器都支持
- 原生的浏览器api,不需要引入外部的代码(插件,组件)
- 向后兼容
- 成熟稳定
缺点
- 接口复杂,代码量较大
- 容易陷入回调地狱
jQuery.ajax
该类库被广泛使用于异步HTTP请求,直到新一代的框架出一。
所有的jQuery Ajax方法返回一个XMLHTTPRequest对象的超集。
GET
$.ajax({
url: 'http://dataserver/data.json'
}).done(function(data) {
// ...do some stuff whith data
}).fail(function() {
// Handle error
});
POST
$.ajax({
type: "POST",
url: 'http://dataserver/update',
data: data,
success: successCallBack,
error: errorCallBack,
dataType: dataType
});
优点
- Good support and documentation 社区支持和文档都很好
- 可配置
- 大量项目在使用
- 学习曲线低
- 可中止ajax请求,因为返回的是XMLHTTPRequest对象
缺点
- No working with promises 不支持Promises
- 非浏览器原生API
- 与原生Fetch不兼容
Qwest
Qwest是一个基于promises简单的ajax库,支持XmlHttpRequest2特性,可以传输ArrayBuffer,Blob和FormData等类型数据。
GET
qwest.get('http://dataserver/data.json')
.then(function(xhr, response) {
// ...do some stuff whith data
});
POST
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
});
优点
- 设置请求限制
- 基于Promise
缺点
- 支持XmlHttpRequest2,但不是所有浏览器
- 非浏览器原生API
SuperAgent
SuperAgent Ajax API,具胡灵活性、可读性和较低的学习曲线等特性。同时适用于node.js。
GET
request('GET', 'http://dataserver/data.json').then(
success, failure);
The .query() method accepts objects, which, when used with the GET method, will form a query-string. The following will produce the path /dataserver/search?name=Manny&lastName=Peck&order=desc.
.query()方法接收objects对象为参数,在GET方法中,可以自动拼接查询字符串,如接下来的例子会拼接成一个“ /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)}
});
POST
request
.post('http://dataserver/update')
.send({ name: 'Murdock' })
.set('Accept', 'application/json')
.then(res => {
console.log('result' + JSON.stringify(res.body));
});
优点
- 基于Promise
- 支持各浏览器及node.js
- 可中止请求,且唤起已中止的请求
- 社区支持良好
- 接口优良
- 支持请求失败自动重发
缺点
- 无法像XMLHttpRequest一样监视请求进度
- 非原生API,需要引入相关组件
Http-client
Http-client 可以让你像fetch一样写http clients。
Get
//using ES6 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)
})
Post
//using ES6 modules
import { createFetch, method, params } from 'http-client'const fetch = createFetch(
params({ name: 'Murdock' }),
base('http://dataserver/update')
)
优点
- 适用于浏览器、nodejs
- 被用作Service Workers
- 基于Promise
- 提供请求头部防篡改,以防CORS安全隐患
缺点
- 非原生API
Axios
Vue官方推荐AJAX请求组件,非常流行。
Get
axios({
url: 'http://dataserver/data.json',
method: 'get'
})
Post
axios.post('http://dataserver/update', {
name: 'Murdock'
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
优点
- 使用promises以防止回调地狱
- 浏览器及node.js都适用
- Support for upload progress
- Can set a response timeout
- Configure your requests by simply passing a configuration object to it
- Axios has implemented the cancellable promise proposal
- Automatically converts the data to JSON
Cons
- 非原生API
Fetch
Fetch API 提供了一个 JavaScript 接口,用于访问和操纵 HTTP 管道的一些具体部分,例如请求和响应。它还提供了一个全局 fetch() 方法,该方法提供了一种简单,合理的方式来跨网络异步获取资源。
Get
//With ES6 fetch
fetch('http://dataserver/data.json')
.then(data => {
// ...do some stuff whith data
}).catch(error => {
// Handle error
});
Post
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));//OR with ES2017 for example(async () => {
const response = await fetch('http://dataserver/update', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({name='Murdock'})
});const result = await response.json();console.log(result);
})();
优点
- 浏览器原生 API
- Fetch 是xmlhttprequest的加强版
- 使用 promises 防止回调地狱
- 无需依赖项
- 易学易用
- 主流浏览器都支持
缺点
- 处理json数据时需要分成两步走。第一步是要发送请求,第二步需要调用json()方法。而在axios你能默认返回json.
- 当接收到一个代表错误的 HTTP 状态码时,从 fetch() 返回的 Promise 不会被标记为 reject, 即使响应的 HTTP 状态码是 404 或 500。相反,它会将 Promise 状态标记为 resolve (但是会将 resolve 的返回值的 ok 属性设置为 false ),仅当网络故障时或请求被阻止时,才会标记为 reject。
- 缺少abort,cancel等功能
fetch()
**不会接受跨域 cookies;**你也不能使用fetch()
建立起跨域会话。其他网站的[Set-Cookie](https://wiki.developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie)
头部字段将会被无视。fetch
不会发送 cookies。除非你使用了_credentials_ 的初始化选项。(自 2017 年 8 月 25 日以后,默认的 credentials 政策变更为same-origin
。Firefox 也在 61.0b13 版本中进行了修改)
总结
Fetch是新标准,新版本的Chrome和Firefox已经支持,不需要任何组件。
同时,也推荐Axios,SuperAgent以及本文其它类库,它们使用起来都很简单。有些场景,比fetch还好用。
说了这么多,就我而言,**我选择Fetch。**就我的项目而言,Fetch完全够用了,还很新潮。
谢谢阅读,希望对你有帮助。