JavaScript中各种发送HTTP请求方式的比较

[广告:最高 ¥2000 红包]阿里云服务器、主机等产品通用,可叠加官网常规优惠使用 | 限时领取

原文: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 头部字段将会被无视。
  • fetch 不会发送 cookies。除非你使用了credentials 的初始化选项。(自 2017 年 8 月 25 日以后,默认的 credentials 政策变更为 same-origin。Firefox 也在 61.0b13 版本中进行了修改)

总结

Fetch是新标准,新版本的Chrome和Firefox已经支持,不需要任何组件。

同时,也推荐Axios,SuperAgent以及本文其它类库,它们使用起来都很简单。有些场景,比fetch还好用。

说了这么多,就我而言,我选择Fetch。就我的项目而言,Fetch完全够用了,还很新潮。

谢谢阅读,希望对你有帮助。

码中人 微信公众号

关注微信公众号

码中人 微信公众号