Ajax

  • XMLHttpRequest对象 同/异 步
  • 属性
  • readyState
  • get请求
  • post请求
  • ajax在IE
  • Ajax的缺点
  • jQuery中的ajax
  • Headers 对象
  • Request 对象
  • Fetch API 异步
  • 基本用法
  • 获取二进制数据
  • Beacon API
  • web Socket



Ajax Asynchronous Javascript +XML


本质:远程脚本


Ajax-无需刷新当前页面即可从服务器获取额外数据的一个方法.


最初是通过JavaScript从服务器获取XML数据的一种手段

  • 最初,JavaScript对服务器的请求可以通过中介(如Java小程序、或flash影片),即远程脚本
  • 在XHR出现之前Ajax风格的通信必须通过黑科技实现-隐藏的窗格、内嵌窗格。
  • XHR由微软提出,又被其他浏览器借鉴,打开一个新的HTTP请求,并指定该HTTP请求的方法、URL及验证信息,提供了原生的浏览器通信能力。
    XHR为发送服务器请求和获取响应提供了合理的接口,该接口可以实现同/异步从服务器获取额外的数据,即用户不用点击页面刷新也可以获得新的数据。
  • XHR的API被认为比较难用,所以又推出了fetch API,后者支持promise、service worker。

通过XHR进行请求有一个主要限制是跨域安全策略,默认情况下,XHR只允许访问 与发起请求的页面在同一个域的资源。想要实现跨域XHR,从实现跨域HTTP入手,CORS方法、CSP头部。此外也可以直接不用XHR,采用其他不受跨域限制的方法,jsonp、img图片探测

解决跨域

XMLHttpRequest对象 同/异 步

XMLHttpRequest对象 fetch API
一个异/同步(配置open方法的参数来实现同/异 步)调用对象,设置响应HTTP请求状态变化的函数

let xhr=new  XMLHttpRequest();

//收到响应后,xhr的部分属性会被填充赋值
xhr.onreadystatechange=function(){
	if(xhr.readyStatus==4){
		if(xhr.status>=200&&xhr.status<300||xhr.status==304){
			alert(xhr.responseText);
		}else{
			alert("Request failed :"+xhr.status);
		}//不用this取代xhr,防止作用域问题
	}
};

xhr.open("get","./url",请求是否异步的布尔值);//请求方法,不请求,只是做准备,只能访问同源URL
//修改添加 应在这时完成
xhr.send(请求体);//无请求体,传入null

一般浏览器自己的默认HTTP消息头都会携带上去,此外
open()与send()函数之间开发者可以使用setRequestHeader()发送自定义的头部

属性

  1. responseText:作为响应体返回的文本
  2. responseXML:当响应体是XML时
  3. status:响应的HTTP状态
  4. statusText:响应的HTTP状态描述
  5. readyState:当前处在请求/响应过程的哪一阶段0-4,会触发readystatechange事件,为了保证跨流域兼容,onreadystatechange事件处理程序应该在调用open()之前赋值。
  6. timeout:毫秒数,不响应触发timeout事件,超时之后访问state会报错,在onreadyState写好catch/try

还有其他进度事件:loadstars、progress、error、

readyState

status是服务器对请求的反馈,而readystate表明客户端的交互状态过程。
ajax.readyState由AJAX对象与服务器交互时所得。无论访问结果如何,运行ajax都一定经历过的状态,即AJAX运行步骤。
(由数字1~4单位数字组成)

0 - (未初始化)还没有调用send()方法
1 - (载入)已调用send()方法,正在发送请求
2 - (载入完成)send()方法执行完成,
3 - (交互)正在解析响应内容
4 - (完成)响应内容解析完成,可以在客户端调用了

监听readyState可以实现解析完成立即调用

get请求

在get请求后添加的查询字符串参数,必须正确编码添加到URL后,然后再传给open()
encodeURLComponent编码,&分割所有名/值对

可以自定义一个addURLParam()来保证编码正确

function addURLParam(url,name,value){
	url+=(url.indexOf("?")==-1? "?":"&");
	url+=endodeURIComponent(name)+"="+endodeURIComponent(value);
	return url;
}

post请求

相比get请求占更多资源,速度慢
向服务器发送应该保存的数据,应该再请求体中携带提交的数据,数据可以是任意格式

默认,服务器而言POST与提交表单不一样。提交表单可以通过添加头部Content-Type来告诉服务器,再通过调用serialize函数序列化表单数据之后作为请求体。除此之外,XHR 2新增了FormData类,保存表单数据,直接可以作为请求体,无需添加特殊头部.

const form = document.getElementById('iii');
xhr.send(serialize(form));
xhr.send(new FormData(form));
// 也可以这样添加数据
FormData.append('key','value')
ajax在IE

在IE浏览器,如果请求的方法是GET,并且请求的URL不变,那么这个请求的结果就会缓存。解决方法就是实时修改请求的URL,只要URL改变,就不会缓存

Ajax的缺点

不支持浏览器的back按钮
又安全问题,Ajax暴露了与服务器交互的细节
对搜索引擎不友好
破坏了程序的异常机制
不容易调试

jQuery中的ajax

$.get(url,[data],[callback])
$.getJSON(url,[data],[callback])
$.post(url,[data],[callback])
$.ajax(option)
$.getScript(url,[data],[callback])
jquery对象.load(url,[data],[callback])

Headers 对象

对象是所有外发请求和入站响应头部的容器,类似Map对象。

get()、set()、deleted()、keys()、values()、entries(),此外

let seed={foo:'bar'};
let h=new Headers(seed);

注意有些情况头部是不允许被更改的,这时候上述函数就会报错

每个外发/入站的Response实例都包含一个Headers实例,可以通过Response.prototype.headers访问

Request 对象

获取资源请求的接口
在fetch中可以传入Request对象
有请求体的对象只能使用一次,因为请求体会被标记为已使用

Fetch API 异步

支持promise、service worker
能够执行XHR对象的所有任务,但更容易使用,是使用js请求资源的工具。
fetch方法给指定URL发送请求,是暴露在全局作用域中,包括主页面执行线程、模块和工作线程。

基本用法
let r=fetch('/资源的url');//返回一个promise
r.then( (response) => {
	response.text
})

获取二进制数据

通常后端返回给我们的数据格式是json,获取数据时直接res.json就可以。除此之外,还有其他的格式

过去获取二进制数据,需要通过XMLHttpRequest对象的overrideMimeType方法来重载所获取数据的MIME类型,将所获取数据的字符编码charset修改为用户自定义类型。
HML5的XMLHttpRequest对象新增了responseType(属性值见下) 与response属性

arraybuffer:response 是一个包含二进制数据的 JavaScript ArrayBuffer。
blob:response 是一个包含二进制数据的 Blob 对象 。
document:response 是一个 HTML Document 或 XML XMLDocument,这取决于接收到的数据的 MIME 类型。
json:response 是一个 JavaScript 对象。这个对象是通过将接收到的数据类型视为 JSON 解析得到的。
text:response 是一个以 DOMString 对象表示的文本。

Beacon API

是一个基于JavaScript的Web api,一种非常有用的记录运动方法,可以将数据从页面发送回服务器,尤其是在日志记录环境中,浏览器支持非常广泛,能够无缝地记录数据,而不影响用户体验和网页性能,请求的非阻塞性质意味着性能比XHR和Fetch等替代方案快得多。

信息少量而快速

类似unload这样的情况下成功发送请求,同时不影响下一个页面的载入
任何时候都可以调用,浏览器会把请求添加到一个内部的请求队列,浏览器会主动地发送队列中的请求。
浏览器保证在原始页面已经关闭的情况下也会发送请求。
给navigator添加了一个sendBeacon()方法

navigator.sendBeacon(‘url',数据的有效负载参数);

web Socket

得到了所有主流浏览器的支持
是与服务器的全双工、双向通信渠道,不使用HTTP,而是自定义协议。目的是更快地发送小数据块。这需要支持该协议的专用的服务器,但速度优势明显。
使用JavaScript创建web socket时,一个Http请求会发送到服务器以初始化连接,服务器响应后,使用HTTP的upgrade头部从HTTP协议切换到其他协议。

let socket=new WebSocket("ws://www.example.com/server.php");//不限制同源
socket.send("hihi");
//服务器回答消息,会触发message消息,可通过event.data访问到消息