首页 > 其他分享 >第二十篇 Ajax 与 Comet

第二十篇 Ajax 与 Comet

时间:2023-04-05 22:56:43浏览次数:40  
标签:status 请求 xhr XHR 响应 Ajax Comet 第二十

by caix in 深圳
Ajax是一种从页面向服务器请求数据的技术,Comet是一种服务器向页面推送数据的技术,能够让信息近乎实时的被推送到页面上。

实现 Comet方式:长轮询,流

主流的 Web端 即时通讯方案大致有4种:传统Ajax短轮询、Comet技术、WebSocket技术、SSE(Server-sent Events)

Ajax

Ajax 是对Asynchronous JavaScript + XML的简写

Ajax 技术的核心是 XMLHttpRequest对象(简称 XHR)
XMLHttpRequest 对象

IE7+、Firefox、Opera、Chrome 和 Safari 都支持原生的 XHR 对象,在这些浏览器中创建 XHR 对象 要像下面这样使用 XMLHttpRequest 构造函数

定义

let xhr = new XMLHttpRequest()

完整版本

 // 先检测原生 XHR 对象是否存在,如果存在则返回它的新实例
 
var createXHR = () => {

 // 先检测原生 XHR 对象是否存在,如果存在则返回它的新实例
if (typeof XMLHttpRequest != "undefined"){ 
   return new XMLHttpRequest(); 
  // 如果原生对象不存在,则检测 ActiveX 对象
   } else if (typeof ActiveXObject != "undefined"){ 
   if (typeof arguments.callee.activeXString != "string"){ 
     var versions = [ "MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0", 
     "MSXML2.XMLHttp"], 
     i, len; 
     for (i=0,len=versions.length; i < len; i++){ 
       try { 
       new ActiveXObject(versions[i]); 
       arguments.callee.activeXString = versions[i]; 
       break; 
       } catch (ex){ 
       //跳过
       } 
   } 
   } 
   	return new ActiveXObject(arguments.callee.activeXString); 
   } else { 
   	 throw new Error("No XHR object available."); 
   } 
}
}
使用方法

1、open()

xhr.open("get", "example.php", false); 

要发送的请求的类型("get"、"post"等)、请求的 URL 和表示是否异步发送请求的布尔值用 open() 方法并不会真正发送请求,而只是启动一个请求以备发送。

2、send()

接收一个参数,即要作为请求主体发送的数据。

如果不需要通过请求主体发送数据,则必须传入 null,因为这个参数对有些浏览器来说是必需的。

在收到响应后,响应的数据会自动填充 XHR 对象的属性,相关的属性简介如下。


responseText:作为响应主体被返回的文本。

responseXML:如果响应的内容类型是"text/xml"或"application/xml",这个属性中将保存包含着响应数据的 XML DOM 文档。

status:响应的 HTTP 状态。

同步请求

xhr.open("get", "example.txt", false); 
xhr.send(null); 
//状态代码为 304 表示请求的资源并没有被修改,可以直接使用浏览器中缓存的版本;当然,也意味着响应是有效的。
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){ 
 alert(xhr.responseText); 
} else { 
 alert("Request was unsuccessful: " + xhr.status); 
}

但多数情况下,我们还是要发送异步请求,才能让JavaScript 继续执行而不必等待响应。此时,可以检测 XHR 对象的 readyState 属性,该属性表示请求/响应过程的当前活动阶段。该属性可取:

0:未初始化。尚未调用 open()方法。


1:启动。已经调用 open()方法,但尚未调用 send()方法。


2:发送。已经调用 send()方法,但尚未接收到响应。


3:接收。已经接收到部分响应数据。


4:完成。已经接收到全部响应数据,而且已经可以在客户端使用了。

只要 readyState 属性的值由一个值变成另一个值,都会触发一次readystatechange 事件。可以利用这个事件来检测每次状态变化后 readyState 的值

总体创建 ajax

// 一、创建Ajax实例
let xhr = new XMLHttpRequest(); //IE下为ActiveObject对象

//二、打开请求: 发送请求之前的一些配置项
//1.HTTP METHOD:GET/POST/PUT/DELETE/HEAD/OPTIONS/TRACE/CONNECT/
//2.url:接口地址
//3.async:设置Ajax的同步异步,默认是异步
//4.user-name/user-pass用户名和密码,一般不用
xhr.open(method, url, async, [user-name], [user-pass])

//三、事件监听:一般监听的都是readystatechange事件(Ajax状态改变事件),基于这个事件可以获取服务器返回的响应头响应主体
xhr.onreadystatechange = () => {
	if(xhr.readyState === 4 && xhr.status === 200){
		console.log(xhr.responseText);
	}
};

//四、发送Ajax请求:从这步开始,当前Ajax任务开始,如果Ajax是同步的,后续代码不会执行,要等到Ajax状态成功后再执行
xhr.send([请求主体内容])

3、xhr.abort();

接收到响应之前还可以调用 abort()方法来取消异步请求
XMLHttpRequest 2 级
XMLHttpRequest 1级 只是把已有的 XHR 对象的实现细节描述了出来

XMLHttpRequest 2级 则进一步发展了 XHR

1、FormData

现代 Web 应用中频繁使用的一项功能就是表单数据的序列化,XMLHttpRequest 2 级为此定义了 FormData 类型

var xhr = createXHR(); 
xhr.onreadystatechange = function(){ 
 if (xhr.readyState == 4){ 
   if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){ 
      alert(xhr.responseText);
    } else { 
      alert("Request was unsuccessful: " + xhr.status); 
    } 
 	} 
}; 
xhr.open("post","postexample.php", true); 

// 添加FormData数据
var form = document.getElementById("user-info");
xhr.send(new FormData(form));

使用 FormData 的方便之处体现在不必明确地在 XHR 对象上设置请求头部。XHR 对象能够识别传入的数据类型是 FormData 的实例,并配置适当的头部信息。
支持 FormData 的浏览器有 Firefox 4+、Safari 5+、Chrome 和 Android 3+版 WebKit

2、超时设定

IE8 为 XHR 对象添加了一个 timeout 属性,表示请求在等待响应多少毫秒之后就终止

var xhr = createXHR(); 
xhr.onreadystatechange = function(){ 
 if (xhr.readyState == 4){ 
   try { 
     if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){ 
     		alert(xhr.responseText); 
     } else { 
     		alert("Request was unsuccessful: " + xhr.status); 
     } 
     } catch (ex){ 
     		//假设由 ontimeout 事件处理程序处理
     } 
 	} 
}; 
xhr.open("get", "timeout.php", true); 
xhr.timeout = 1000; //将超时设置为 1 秒钟(仅适用于 IE8+)
xhr.ontimeout = function(){ 
 alert("Request did not return in a second."); 
}; 
xhr.send(null);

3、进度事件

Progress Events 规范是 W3C 的一个工作草案,定义了与客户端服务器通信有关的事件。这些事件最 早其实只针对 XHR 操作,但目前也被其他 API 借鉴。有以下 6 个进度事件

oadstart:在接收到响应数据的第一个字节时触发。
progress:在接收响应期间持续不断地触发。
error:在请求发生错误时触发。
abort:在因为调用 abort()方法而终止连接时触发。
load:在接收到完整的响应数据时触发。
loadend:在通信完成或者触发 error、abort 或 load 事件后触发。

4、progress事件

对 XHR 的另一个革新是添加了progress\color{#0000FF}{progress}progress事件,这个事件会在浏览器接收新数据期间周期性地触发。而onprogress\color{#0000FF}{onprogress}onprogress事件处理程序会接收到一个event\color{#0000FF}{event}event对象,其 target 属性是 XHR 对象,但包含着三个额外的属性:lengthComputable、position 和 totalSize。

engthComputable是一个表示进度信息是否可用的布尔值,
position 表示已经接收的字节数
totalSize 表示根据
Content-Length 响应头部确定的预期字节数。

var xhr = createXHR(); 
xhr.onload = function(event){ 
 if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){ 
    alert(xhr.responseText); 
 } else { 
    alert("Request was unsuccessful: " + xhr.status); 
 } 
}; 
// open 之前调用,每次触发都会以新的状态信息更新 HTML 元素的内容
//如果响应头部中包含Content-Length 字段,那么也可以利用此信息来计算从响应中已经接收到的数据的百分比。
xhr.onprogress = function(event){ 
 var divStatus = document.getElementById("status"); 
 if (event.lengthComputable){ 
   divStatus.innerHTML = "Received " + event.position + " of " + 
   event.totalSize +" bytes"; 
 } 
}; 
xhr.open("get", "altevents.php", true); 
xhr.send(null);

在这里我们一定想到了最常写的图片上传并显示进度百分比的业务,就是通过监听progress
跨资源共享
1.CORS

我们都知道ajax是同源策略,协议、域名、端口一致。 CORS(Cross-Origin Resource Sharing,跨源资源共享是 W3C 的一个工作草案,定义了在必须访问跨源资源时,浏览器与服务器应该如何沟通

CORS 背后的基本思想,就是使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功,还是应该失败

var xhr = createXHR(); 
xhr.onreadystatechange = function(){ 
 if (xhr.readyState == 4){ 
   if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){ 
      alert(xhr.responseText); 
   } else { 
      alert("Request was unsuccessful: " + xhr.status); 
   } 
 } 
}; 
xhr.open("get", "http://www.somewhere-else.com/page/", true); 
xhr.send(null);

2、带凭据请求

默认情况下,跨源请求不提供凭据(cookie、HTTP 认证及客户端 SSL 证明 等 )。 通 过 将 withCredentials属性设置为 true,可以指定某个请求应该发送凭据。如果服务器接受带凭据的请 求,会用下面的 HTTP 头部来响应

Access-Control-Allow-Credentials: true
其他跨域技术
1. 图像ping

原理:利用标签的src属性,图像 Ping 是与服务器进行简单、单向的跨域通信的一种方式。

请求的数据是通过查询字符串形式发送的,而响应可以是任意内容,但通常是像素图或 204 响应。

缺点:
1.只能发送 GET 请求
2.无法访问服务器的响应文本。

因此,图像 Ping 只能用于浏览器与服务器间的单向通信。

2. JSONP

JSONP是JSON withpadding(填充式 JSON 或参数式 JSON)的简写,是应用 JSON 的一种新方法,

JSONP 由两部分组成:回调函数和数据。回调函数是当响应到来时应该在页面中调用的函数。回调函数的名字一般是在请求中指定的。而数据就是传入回调函数中的JSON数据。

原理:通过<script>标签里不受限制地从其他域加载资源

3. Comet

指的是一种更高级的 Ajax 技术,Ajax 是一种从页面向服务器请求数据的技术,而 Comet 则是一种服务器向页面推送数据的技术。Comet 能够让信息近乎实时地被推送到页面上,非常适合处理体育比赛的分数和股票报价

有两种实现 Comet 的方式:长轮询和流。长轮询是传统轮询(也称为短轮询)的一个翻版,即浏览器定时向服务器发送请求,看有没有更新的数据。

两者最大的区别:

在于服务器如何发送数据

   短轮询是服务器立即发送响应,无论数据是否有效,

   长轮询是等待发送响应。

轮询的优势是所有浏览器都支持,因为使用 XHR 对象和 setTimeout()就能实现。而你要做的就是决定什么时候发送请求

所有浏览器都支持长轮询,而只有部分浏览器原生支持 HTTP 流

4、其他

SSE(Server-Sent Events,服务器发送事件)是一种实现 Comet 交互的浏览器 API,既支持长轮询,也支持 HTTP 流。SSE API用于创建到服务器的单向连接,服务器通过这个连接可以发送任意数量的数据

Web Sockets 是一种与服务器进行全双工、双向通信的信道。与其他方案不同,Web Sockets 不使用 HTTP 协议,而使用一种自定义的协议。这种协议专门为快速传输小数据设计。虽然要求使用不同的 Web 服务器,但却具有速度上的优势

标签:status,请求,xhr,XHR,响应,Ajax,Comet,第二十
From: https://www.cnblogs.com/caix-1987/p/17291222.html

相关文章

  • 第二十一篇 离线应用与客户端存储
    bycaixin深圳离线应用支持离线Web应用开发是HTML5的另一个重点。所谓离线Web应用,就是在设备不能上网的情况下仍然可以运行的应用开发离线Web应用需要几个步骤。首先是确保应用知道设备是否能上网,以便下一步执行正确的操作。然后,应用还必须能访问一定的资源(图像、Java......
  • 第二十三篇 最佳实践 - 可维护性
    bycaixin深圳可维护性在早期网站中,JavaScript主要用于实现一些小型动效或表单验证。今天的Web应用则动辄成千上万行JavaScript代码,用于完成各种各样复杂的处理。这些变化要求开发者把可维护能力放到重要位置上。正如更传统意义上的软件工程师一样,JavaScript工程师受雇......
  • 第二十二篇 高级技巧
    bycaixin深圳高级技巧-高级函数在JavaScript里面,函数拥有非常高的特权,甚至是一等公民,因此也跟Kotlin一样支持多种编程范式一些写函数时的高级技巧纯函数高阶函数函数缓存懒函数柯里化函数组合纯函数纯函数要满足两个条件:1、给相同的参数返回相同的结果2、......
  • 第二十四篇 最佳实践 - 性能
    bycaixin深圳前端性能优化最佳实践客户端性能、服务器端、网络性能1、页面内容减少HTTP请求数减少DNS查询避免重定向缓存Ajax请求延迟加载预先加载减少DOM元素数量划分内容到不同域名尽量减少iframe使用避免404错误2、服务器使用CDN添加Expi......
  • 第二十届浙大城市学院程序设计竞赛 I.Magic Tree DFS序线段树
    传送门大致思路:  我们知道dfs序上的整颗子树dfs序编号连续,因为每次删除一个点或者新增一个点都导致子树上所有点的深度加一或者减一。由于是区间修改所以我们考虑dfs序上建线段树。  #include<iostream>#include<cstring>#include<iomanip>#include<algorithm>#in......
  • jQuery实现Ajax通讯的几种常用方式
    这里介绍3种jQuery.get(url,[data],[success(data,textStatus,jqXHR)],[dataType])jQuery.post(url,[data],[success(data,textStatus,jqXHR)],[dataType])jQuery.ajax(url,[settings])第三种是我最常用的,看个人习惯了,其实都OK第一种不支持中文,要用......
  • 牛客,第二十届北京师范大学程序设计竞赛,签到题7题
    序题号标题已通过代码通过率团队的状态A小凯的疑惑点击查看434/745通过B幻象踩花点击查看121/434通过C跳刀抓人点击查看26/178通过D真正的卡尔点击查看115/714通过E刷新的艺术点击查看31/479通过F最后的战役点击查看1/39未通过G随机数生成器点击......
  • Domino (贪心,多个位置排序,优先队列) 第二十届浙大城市学院程序设计竞赛
    题目大意:给出2个队列A,B选K个ai和在从里面选L个bi问权值最大时多少   思路:排序预处理有多个元素的时候,对那个元素首先排序,以至于可以处理这个问题是很重要的当不能一步直接贪心出来,可以先贪部分,然后利用DP的思想慢慢加入点去更新即可先对ai排序,......
  • Maze 第二十届浙大城市学院程序设计竞赛 (二分图,网络流(对于表格,矩阵是如何建边的))
    题目大意:给出一个01矩阵,给出q,p分别表示选一个点的权值,和选2个连在一起的点的权值问如何让权值更大 注意:在Dinic的时间复杂度对于二分图这种边权为1,时间复杂度为NsqrtN, 不是n^2m  思路:更具题目的条件限制,他的建边一定是2个矮在一起的因此更具(i......
  • urilib: ajax&异常&cookie登陆&handler&代理[池]
    urllib_9_ajax的get请求豆瓣电影第一页""".-''-..--._..._.'.-.)|__|......