关键词搜索

全站搜索
×
密码登录在这里
×
注册会员
×

已有账号? 请点击

忘记密码

已有账号? 请点击

使用其他方式登录

$.ajax,axios,fetch,原生XHR四种ajax区别

发布2022-05-13 浏览552次

详情内容

在前端开发时,离不开前后端数据交互,通过ajax后端接口取数据,   Ajax是常用的一门与Web服务器通信的技术,目前发送Ajax请求的主要有4种方式:

  1. 原生XHR

  2. jquery中的$.ajax()

  3. axios

  4. fetch

原生XMLHttpRequest

代码实例

原生AJAX API 中核心提供的是一个 XMLHttpRequest 类型,所有的 AJAX 操作都需要使用到这个类型。

var request = new XMLHttpRequest(); // 创建XMLHttpRequest对象//ajax是异步的,设置回调函数request.onreadystatechange = function () { // 状态发生变化时,函数被回调
    if (request.readyState === 4) { // 成功完成
        // 判断响应状态码
        if (request.status === 200) {
            // 成功,通过responseText拿到响应的文本:
            return success(request.responseText);
        } else {
            // 失败,根据响应码判断失败原因:
            return fail(request.status);
        }
    } else {
        // HTTP请求还在继续...
    }}// 发送请求:request.open('GET', '/api/categories');request.setRequestHeader("Content-Type", "application/json") //设置请求头request.send();//到这一步,请求才正式发出


使用原生的js还是比较繁琐,实际工程中建议使用jQuery之类的库,封装的ajax请求方法非常好用,且解决了浏览器兼容性的问题。

Jquery ajax

代码示例

$.ajax({
 type:"GET",
 url:url,
 data:data,
 dataType:dataType success:function(){},
 error:function(){}})


以上代码,是Jquery对原生XHR的封装,另外还增加了jsonp的支持,让ajax请求可以支持跨域请求,x需要注意的是: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",
						 // 服务端用于接收callback调用的function名的参数
						 jsonp: "", 
						 // callback的function名称
						 jsonpCallback:"weather_callback", 
						 success : function(json){
						 	console.log(json); //浏览器调试的时候用
					 	},
						error:function(){
							alert('fail');
						}
					 });
				});
			});
		</script>
	</body></html>


效果如下:
image.png

当点击以上文字时,查看xhr请求,发现并没有发出xhr请求
image.png

再查看js请求,发现js发出了一个请求,因此jsonp本质是js请求而并非xhr请求,只是$.ajaxjsonp请求封装到了ajax里面而已。
image.png

其实jquery ajax使用起来已经是很方便了,那为什么现在还会被慢慢抛弃呢?个人认为主要原因有以下几点:

  1. 要使用jquery ajax必须引入jquery整个大文件,不是很划算;

  2. jquery ajax本身是针对MVC设计模式的编程,与当前流行的基于MVVM模式的vuereact等框架不符合;

  3. jquery ajax本质是基于XHR的封装,而XHR本身架构不是很清晰,目前已采用fetch代替方案

总结

随着前端基于MVVM模式的VueReact新一代框架的兴起,以及ES6等新规范的制定,像Jquery这种大而全的JS库注定是要走向低潮的。

Axios

代码示例

axios({
	method: 'post',
	url: '/login',
	data: {
		username:'martin',
		password:'a1234567'
	}}).then(function (res) {
	console.log(res);}).catch(function (err) {
	console.log(err);});


axios 是一个基于Promise 用于浏览器和 nodejsHTTP 客户端,本质上也是对原生XHR的封装,只不过它是Promise的实现版本,符合最新的ES规范,有以下几条特性:

  1. 从浏览器中创建XMLHttpRequests

  2. node.js中创建http请求

  3. 支持Promise API

  4. 支持转换请求数据和响应数据

  5. 支持拦截请求和响应

  6. 支持取消请求

  7. 自动转换 JSON 数据

  8. 客户端支持防御CSRF攻击

总结

Axios除了和Jquery ajax一样封装了原生的XHR,还提供了很多比如:并发请求、拦截等多种接口,同时它的体积还比较小,也没有下文fetch的各种问题,可以说是目前最佳的ajax请求方式了。

Fetch

代码示例

Fetch的功能与 XMLHttpRequest 基本相同,但有三个主要的差异:

  1. fetch()使用 Promise,不使用回调函数,因此大大简化了写法,写起来更简洁;

  2. 采用模块化设计,API 分散在多个对象上(Response 对象、Request 对象、Headers 对象);

  3. 通过数据流(Stream 对象)处理数据,可以分块读取,有利于提高网站性能表现,减少内存占用,对于请求大文件或者网速慢的场景相当有用。XMLHTTPRequest 对象不支持数据流,所有的数据必须放在缓存里,不支持分块读取,必须等待全部拿到后,再一次性吐出来。

用法:

fetch('url请求地址')
  .then(response => response.json())
  .then(json => console.log(json))
  .catch(err => console.log('Request Failed', err));


上面示例中,fetch()接收到的response是一个 Stream 对象,response.json()是一个异步操作,取出所有内容,并将其转为 JSON 对象。
Promise 可以使用 await 语法改写,使得语义更清晰。

async function getJSON() {
	try{
		var response=await fetch(url);
		var data=response.json();
		console.log(data);
	}catch(e){
		console.log('error is'+e); 
	}}


await语句必须放在try...catch里面,这样才能捕捉异步操作中可能发生的错误。

此外,需要注意一下几点:

1)只有网络错误,或者无法连接时,fetch()才会报错,即使服务器返回的状态码是 4xx5xxfetch()也不会报错(即 Promise 不会变为 rejected状态)。
要判断请求是否成功,一种方法是通过Response.status属性,得到 HTTP回应的真实状态码,才能判断请求是否成功,如下所示:

async function fetchText() {
  let response = await fetch(url);
  if (response.status >= 200 && response.status < 300) {
    return await response.text();
  } else {
    throw new Error(response.statusText);
  }}


上面示例中,response.status属性只有等于 2xx (200~299),才能认定请求成功。这里不用考虑网址跳转(状态码为 3xx),因为fetch()会将跳转的状态码自动转为 200。

另一种方法是判断response.ok是否为true。

if (response.ok) {
  // 请求成功} else {
  // 请求失败}


2)fetch默认不会带cookie,需要添加配置项(credentials属性);

3)fetch没有办法原生监测请求的进度,而XHR可以。

Fetch在使用上说实话目前还没有axiosjquery 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”(透明)的原因。
image.png

总结

Fetch是 XMLHttpRequest 的升级版,虽然部分功能不是十分完善,但是也有它的优势所在。浏览器原生提供该对象,当前浏览器基本都支持。基于promise对象,支持链式写法。

注意点:

1.fetch是有兼容问题的

IE系列是完全不支持的,主流浏览器的早起版本也不支持,所以如果在项目中使用需要做兼容方案处理。

2.fetch 不管请求处理成功还是失败,都会触发promise的resolve状态回掉。这个和传统的ajax 框架是有点区别的。fetch只有当网络故障导致请求发送失败或者跨域的时候才会触发reject的逻辑。我们可以通过response 对象的ok是否是true来判断是否是真正的成功。


    点击QQ咨询
    开通会员
    返回顶部
    ×
    • 微信支付
    微信扫码支付
    微信扫码支付
    请使用微信描二维码支付
    ×

    提示信息

    ×

    选择支付方式

    • 微信支付
    确定支付下载