Ajax是常用的一门与Web服务器通信的技术,目前发送Ajax请求的主要有4种方式:
- 原生XHR
- jquery中的$.ajax()
- axios
- fetch
至于原生的XHR目前工作中已经很少去手写它了,前些年我们比较常用的是jquery的ajax请求,但是近些年前端发展很快,jquery包装的ajax已经失去了往日的光辉,取而代之的是新出现的axios和fetch,两者都开始抢占“请求”这个前端重要领域。本文结合自己的使用经历总结一下它们之间的一些区别,并给出一些自己的理解。
1.Jquery ajax
代码示例:
$.ajax({ type:"GET", url:url, data:data, dataType:dataType success:function(){}, error:function(){} })
以上代码很简单,我就不多解释了,这就是jquery对原生XHR的封装,另外还增加了jsonp的支持,让ajax请求可以支持跨域请求,但是要注意的是:jsonp请求本质不是XHR异步请求,就是请求了一个js文件,因此在浏览器的network面板中的xhr标签下看不到jsonp的跨域请求,但是在js标签下能看见。
jsonp请求示例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>使用jQuery-AJAX--读取获得跨域JSONP数据</title> <script src="./jquery-1.7.2.js" type="text/javascript"></script> <style type="text/css"> body,html{font-family: "Microsoft Yahei";} a{text-decoration: none;} </style> </head> <body> <h2><a href="javascript:void(0)" class="btnAJAX">点击AJAX获取数据JSONP跨域....</a></h2> <script src="jquery.min.js"></script> <script type="text/javascript"> $(function() { $(".btnAJAX").click(function(){ $.ajax({ type : "get", async:false, url : "http://weather.123.duba.net/static/weather_info/101121301.html", dataType : "jsonp", jsonp: "", //服务端用于接收callback调用的function名的参数 jsonpCallback:"weather_callback", //callback的function名称 success : function(json){ console.log(json); //浏览器调试的时候用 }, error:function(){ alert('fail'); } }); }); }); </script> </body> </html>
效果如下:
当点击以上文字时,查看xhr请求,发现并没有发出xhr请求
再查看js请求,发现js发出了一个请求,因此jsonp本质是js请求而并非xhr 请求,只是$.ajax把jsonp请求封装到了ajax里面而已。
其实jquery ajax使用起来已经是很方便了,那为什么现在还会被慢慢抛弃呢?个人认为主要原因有以下几点:
- 要使用jquery ajax必须引入jquery整个大文件,不是很划算
- jquery ajax本身是针对MVC设计模式的编程,与当前流行的基于MVVM模式的vue、react等框架不符合
- jquery ajax本质是基于XHR的封装,而XHR本身架构不是很清晰,目前已采用fetch代替方案
总结
随着前端基于MVVM模式的Vue和React新一代框架的兴起,以及ES6等新规范的制定,像Jquery这种大而全的JS库注定是要走向低潮的。
2.Axios
代码示例:
axios({ method: 'post', url: '/login', data: { username:'martin', password:'a1234567' } }) .then(function (res) { console.log(res); }) .catch(function (err) { console.log(err); });
这种ajax请求方式是Vue框架的作者尤雨溪开始推荐使用的。其实Axios的本质也是基于原生XHR的封装,只不过它是基于ES6的新语法Promise的实现版本。并且具有以下几条特性:
- 从浏览器中创建XHR
- 从node.js中创建http请求
- 支持promise API
- 提供了并发请求的接口(重要,方便操作)
- 支持拦截请求和响应
- 支持取消请求
- 客户端支持防御CSRF攻击
总结
Axios除了和jquery ajax一样封装了原生的XHR,还提供了很多比如:并发请求、拦截等多种接口,同时它的体积还比较小,也没有下文fetch的各种问题,可以说是目前最佳的ajax请求方式了。
3.Fetch
代码示例:
try{ var response=await fetch(url); var data=response.json(); console.log(data); }catch(e){ console.log('error is'+e); }
上面说的$.ajax和Axios说到底本质都是对原生XHR的封装,但是Fetch可以说是新时代XHR的替代品。它的特性如下:
- 更加底层,提供更丰富的API
- 不基于XHR,是ES新规范的实现方式
但是目前Fetch还存在很多问题
1)fetch只对网络请求报错,对400,500都当做成功的请求
2)fetch默认不会带cookie,需要添加配置项
3)fetch没有办法原生监测请求的进度,而XHR可以
Fetch在使用上说实话目前还没有axios和jquery ajax方便,因此我个人在工作中也是使用axios的比较多。说到这里,你可能觉得Fetch就是强行用ES新规范做出来的代替XHR的半成品,事实上我就是这么认为的。但是有一点Fetch做的性能要远比XHR要好,那就是“跨域的处理”。
因为同源策略的约束,浏览器发送的请求是不能随便跨域的,一定要借助JSONP或者跨域头来协助跨域,而Fetch可以直接设置mode为“no-cors”来实现跨域访问,如下所示
fetch('/login.json', { method: 'post', mode: 'cors', data: {name:martin''} }).then(function() { /* handle response */ });
我们会得到一个type为“opaque”(透明)的response。这个请求是真正抵达过后台的,但是浏览器不可以访问返回的内容,这也就是为什么response中的type为“opaque”(透明)的原因。
总结
Fetch还是一个新时代的半成品,很多地方并不完善,但是也有它的优势所在,总的来说,就是Fetch技术还需要时间的沉淀,目前还没有达到axios的性能。
4.大总结
如果你是直接拉到底部的,就只要记住这个结论就可以啦,目前只需要熟练使用Axios就可以啦,Jquery的ajax会逐渐被时代淘汰,Fetch虽然符合前端潮流,但是目前还尚不成熟,没有Axios使用起来便利。