Javascript 中 ajax 和 axiosfetch 的区别

Posted 福州-司马懿

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Javascript 中 ajax 和 axiosfetch 的区别相关的知识,希望对你有一定的参考价值。

首先介绍一下 BootCDN

BootCDN 是 Bootstrap 中文网支持并维护的前端开源项目免费 CDN 服务,致力于为 Bootstrap、jQuery、Angular、Vuejs 一样优秀的前端开源项目提供稳定、快速的免费 CDN 加速服务。BootCDN 所收录的开源项目主要同步于 cdnjs 仓库。

后续要用到的 JS 插件的CDN地址均可以从该网站找到。

ajax

AJAX = Asynchronous javascript and XML(异步的 JavaScript 和 XML)
AJAX 的作用是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。

XMLHttpRequest 的 readyState 属性

当请求被发送到服务器时,我们需要执行一些基于响应的任务。因此 XMLHttpRequest 提供了 onreadystatechange 函数,每当 readyState 属性发生改变时,就会调用该函数。

onreadystatechange 函数没有参数,参数都存在它的调用者 XMLHttpRequest 里面了。

readyState 一共有 5 种状态

  • 0 请求未初始化
  • 1 服务器连接已建立
  • 2 请求已接收
  • 3 请求处理中
  • 4 请求已完成,且响应已就绪
const xhr = new XMLHttpRequest();
xhr.onreadystatechange=()=>
	console.log( "readyState: " + xhr.readyState );
	console.log( "status: " + xhr.status);

正常 的状态变化流程 2 -> 3 -> 4

访问不存在的页面 的状态变化流程 2 -> 3 -> 4

因此,理论上只需要判断 readyState 为 4 的时候,status 的状态值即可。

XMLHttpRequest 的 status 属性

XMLHttpRequest 对象的 status 和 statusText 属性保存有服务器返回的 http 状态码。

  • status 属性保存的状态码是以数字表示的
  • statusText 属性保存的状态码是以字符串表示的

XMLHttpRequest 对象 status 和statusText 属性对照表

statusstatusText说明
0**-未被始化
1**-请求收到,继续处理
100Continue客户必须继续发出请求
101Switching protocols客户要求服务器根据请求转换HTTP协议版本
2**-操作成功收到,分析、接受
200OK交易成功
201Created提示知道新文件的URL
202Accepted接受和处理、但处理未完成
203Non-Authoritative Information返回信息不确定或不完整
204No Content请求收到,但返回信息为空
205Reset Content服务器完成了请求,用户代理必须复位当前已经浏览过的文件
206Partial Content服务器已经完成了部分用户的GET请求
3**-完成此请求必须进一步处理
300Multiple Choices请求的资源可在多处得到
301Moved Permanently删除请求数据
302Found在其他地址发现了请求数据
303See Other建议客户访问其他URL或访问方式
304Not Modified客户端已经执行了GET,但文件未变化
305Use Proxy请求的资源必须从服务器指定的地址得到
306前一版本HTTP中使用的代码,现行版本中不再使用
307Temporary Redirect申明请求的资源临时性删除
4**-请求包含一个错误语法或不能完成
400Bad Request错误请求,如语法错误
401Unauthorized请求授权失败
402Payment Required保留有效ChargeTo头响应
403Forbidden请求不允许(由于服务器上文件或目录的权限设置导致资源不可用)
404Not Found没有发现文件、查询或URl(没有找到指定的资源)
405Method Not Allowed用户在Request-Line字段定义的方法不允许
406Not Acceptable根据用户发送的Accept拖,请求资源不可访问
407Proxy Authentication Required类似401,用户必须首先在代理服务器上得到授权
408Request Timeout客户端没有在用户指定的饿时间内完成请求
409Conflict对当前资源状态,请求不能完成
410Gone服务器上不再有此资源且无进一步的参考地址
411Length Required服务器拒绝用户定义的Content-Length属性请求
412Precondition Failed一个或多个请求头字段在当前请求中错误
413Request Entity Too Large请求的资源大于服务器允许的大小
414Request-URI Too Long请求的资源URL长于服务器允许的长度
415Unsupported Media Type请求资源不支持请求项目格式
416Requested Range Not Suitable请求中包含Range请求头字段,在当前请求资源范围内没有range指示值,请求也不包含If-Range请求头字段
417Expectation Failed服务器不满足请求Expect头字段指定的期望值,如果是代理服务器,可能是下一级服务器不能满足请求
5**-服务器执行一个完全有效请求失败
500Internal Server Error服务器产生内部错误
501Not Implemented服务器不支持请求的函数
502Bad Gateway服务器暂时不可用,有时是为了防止发生系统过载
503Service Unavailable服务器过载或暂停维修
504Gateway Timeout关口过载,服务器使用另一个关口或服务来响应用户,等待时间设定值较长
505HTTP Version Not Supported服务器不支持或拒绝支请求头中指定的HTTP版本
12029an unknown error occurred while processing the request on the server. the status code returned from the server was : 12029原因:网络不通. 刷新一下就知道了

原生JS

class Ajax 
	get(url, successFn, failFn)
		const xhr = new XMLHttpRequest();
		xhr.open('GET', url, true);
		xhr.onreadystatechange=()=>
			this.deal(xhr, successFn, failFn);
		
		xhr.send();
	
	post(url, data, successFn, failFn)
		const xhr = new XMLHttpRequest();
		xhr.open("POST", url, true);
		// 添加http头,发送信息至服务器时内容编码类型
		xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");  
		xhr.onreadystatechange = function() 
			this.deal(xhr, successFn, failFn);
		;
		xhr.send(data);
	
	deal(xhr, successFn, failFn) 
		//console.log( "readyState: " + xhr.readyState );
		//console.log( "status: " + xhr.status);
		if(xhr.readyState == 4) 
			if(xhr.status == 200 || xhr.status == 304) 
				successFn.call(this, xhr.responseText);
			 else 
				failFn.call(this, xhr.status, xhr.statusText, xhr);
			
		
	

const ajax = new Ajax(); 
ajax.get('http://jsonplaceholder.typicode.com/users/', 
	(responseText)=>
		console.log("success");
		console.log(responseText);
		//这里返回的是PlainText,要转化为JSON/JSONArray,可以用JSON.parse(str)方法
		const responseObj = JSON.parse(responseText);
		console.log(responseObj);
	, (status, statusText, xhr)=>
		console.log("fail");
		console.log(status);
		console.log(xhr);
	
);

可以看到原生返回的只是字符串而已。之所以JQuery之流的插件返回的是JSON对象,是因为在内部调用了JSON.parse方法替我们转化了。

另外,我这里假设服务器返回的数据,json转化一定会成功。但如果服务器下发的不是json数据,那么就会报异常,并且中断后续的执行。

如果这里允许采用降级方案,那么就需要用到 try… catch 函数进行异常捕获了。

const ajax = new Ajax(); 
ajax.get('http://jsonplaceholder.typicode.com/users/', 
	(responseText)=>
		try 
			const responseObj = JSON.parse("xx" + responseText);
			console.log(responseObj);
		 catch(err) 
			console.error(err);
		
		//do something other
	, (status, statusText, xhr)=>
		console.log("fail");
	
);

JQuery

slim 即简化版。比起普通版,少了Ajax和特效模块。

<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
<script>
$.ajax(
	url: 'http://jsonplaceholder.typicode.com/users/',
	type: 'GET',
	dataType: 'json',
	timeout: 500, //0 for no timeout
	async: true, //默认是异步
	data: 
	,
	success: (data, textStatus, jqXHR)=>
		console.log(data); //数据会被转为object或array
		console.log(textStatus); //成功一般返回success
		console.log(jqXHR);
	,
	error: (XMLHttpRequest, textStatus, errorThrown)=>
		console.log(XMLHttpRequest);
		console.log(textStatus);
		console.log(errorThrown);
	
);

成功的情况

数据 data 会被转为 object 或 array,而 textStatus 一般会是 “success”。
注意 jqXHR 指的是 JQuery 自己封装的 XMLHttpRequest,是一个 Object。

失败的情况

如果访问了一个不存在(或者失效)的地址

  • 当 timeout 参数值设的太小的时候,textStatus 和 errorThrown 都会返回 timeout
  • 时间足够(或 不设超时,即timeout 设为 0)的时候,textStatus 会被赋值为“error”,errorThrown会被赋值为 “Not Found”(也就是 statusText 的值)

Zepto

Zepto最初是为移动端开发的库,是jQuery的轻量级替代品,因为它的API和jQuery相似,而文件更小(即使是简化版的 jquery.slim.min 也比 zepto.min 大了一倍)

Zepto最大的优势是它的文件大小,只有8k多,是目前功能完备的库中最小的一个,尽管不大,Zepto所提供的工具足以满足开发程序的需要。大多数在jQuery中·常用的API和方法Zepto都有,Zepto中还有一些jQuery中没有的。

另外,因为Zepto的API大部分都能和jQuery兼容,所以用起来极其容易,如果熟悉jQuery,就能很容易掌握Zepto。你可用同样的方式重用jQuery中的很多方法,也可以方面地把方法串在一起得到更简洁的代码,甚至不用看它的文档。

<script src="https://cdn.bootcss.com/zepto/1.2.0/zepto.min.js"></script>
<script>
$.ajax(
	url: 'http://jsonplaceholder.typicode.com/users',
	type: 'GET',
	dataType: 'json',
	timeout: 500, //0 for no timeout
	async: true, //默认是异步
	data: 
	,
	success: (data, status, xhr)=>
		console.log(data); //数据会被转为object或array
		console.log(status); //成功一般返回success
	,
	error: (xhr, errorType, error)=>
		console.log(xhr);
		console.log(errorType);
		console.log(error);
	
);
</script>

成功的情况

数据 data 会被转为 object 或 array,而 status 一般会是 “success”

失败的情况

如果访问了一个不存在(或者失效)的地址

  • 当 timeout 参数值设的太小的时候,errorType 会被赋为 timeout,而 error 的值为 null【注意:这里与 JQuery 不一样】
  • 时间足够(或 不设超时,即timeout 设为 0)的时候,errorType会被赋值为“error”,error 会被赋值为 “Not Found”(也就是 statusText 的值)

axios

vue2 已经不再维护 vue-resource 这个插件了,而改用基于 Promise 的 axios 插件了。

通过对象指定请求方式的 axios

<script src="https://cdn.bootcss.com/axios/0.19.0-beta.1/axios.min.js"></script>
<script>
axios(
	url: 'http://jsonplaceholder.typicode.com/users/fff',
	type: 'GET',
	responseType: 'json', //这里jquery和zepto用的是dataType
	data: 
	
).then(response=>
	console.log(response);
).catch(error=>
	console.log(error);
);
</script>

成功的情况

失败的情况

速度慢的问题

速度慢是由于中间多发送了一个 OPTIONS 请求。正常情况下,它返回的状态码会被赋为 204,表示服务器收到请求,但返回体为空。

OPTIONS 请求方法的主要用途有两个:

  1. 获取服务器支持的HTTP请求方法;
  2. 用来检查服务器的性能。

304 的含义:
当一个客户端(通常是浏览器)向web服务器发送一个请求,如果web服务器返回304响应,则表示此请求的本地缓存是最新的,可以直接使用。这种方法可以节省带宽,避免重复响应。

3个请求的含义:

  • 根据脚本地址,获取 axios 脚本
  • 发送 OPTIONS 请求,获取服务器支持的 HTTP 请求方法
  • 获取指定URL的JSON数据

直接指定请求方式的 axios

axios.get('http://jsonplaceholder.typicode.com/users/', 
	params: 
).then((response)=>
	console.log(response);
).catch((error)=>
	console.log(error);
);

可以看到直接指定了 axios 的请求方法之后,就不再发送 OPTIONS 请求了。

fetch

fetch 与 jQuery.ajax() 主要有几点不同:

  • 当接收到一个代表错误的 HTTP 状态码时,从 fetch()返回的 Promise 不会被标记为 reject, 即使该 HTTP 响应的状态码是 404 或 500。相反,它会将 Promise 状态标记为 resolve (但是会将 resolve 的返回值的 ok 属性设置为 false ),仅当网络故障时或请求被阻止时,才会标记为 reject。
  • 默认情况下,fetch 不会从服务端发送或接收任何 cookies, 如果站点依赖于用户 session,则会导致未经认证的请求(要发送 cookies,必须设置 credentials 选项)。
var myHeaders = new Headers();
fetch(url, 
	method: 'GET',
    headers: myHeaders,
	credentials: "include"
)
  • fetch不支持JSONP。fetch是与服务器端进行异步交互的,而JSONP是外链一个javascript资源,并不是真正ajax,所以fetch与JSONP没有什么直接关联,当然至少目前是不支持JSONP的。
fetch('http://jsonplaceholder.typicode.com/users/fff')
	.then(response=>
		console.log(response);
		return response.json();
	, err=>
		console.error(err);
	).then(myJson=>
		console.log(myJson);
	);

成功的情况

失败的情况

  • 访问了一个不存在的地址
    fetch 判断是否成功的依据是能否连的上服务器并收到数据。因此需要额外的代码来判断是否是获取错误(错误的情况,response.json() 会返回空对象)

  • 找不到服务器的情况
    只有在找不到服务器,没有收到应答的情况,才会走到 error 函数,否则都会触发success函数。

另外,不管有没有错误发生,后续的then都会被调用。但由于后面 then 函数的参数是前面 then 函数的返回值,由于出错这里是 undefined,否则是空对象()。

以上是关于Javascript 中 ajax 和 axiosfetch 的区别的主要内容,如果未能解决你的问题,请参考以下文章

javascript 使用AJAX(axios)下载文件

JavaScript 使用axios工具包发送Ajax请求

jQuery Ajax 和 axios Ajax

axios和ajax的区别及优缺点

Ajax(Asynchronous Javascript And XML)

AJAX工作原理与Axios的封装