AJAX 是 Asynchronous JavaScript And XML 的简称,它可以让页面在不刷新的情况下从服务器获取数据。
浏览器使用XMLHttpRequest
对象于服务器通信,它可以使用JSON,XML,HTML和text等格式发送和接收数据。
低版本 IE 浏览器没有XMLHttpRequest
对象,但是它可以使用ActiveXObject
对象代替。
if (window.XMLHttpRequest) { // IE7+
XHR = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE 6
XHR = new ActiveXObject("Microsoft.XMLHTTP");
}
创建 XHR 实例过后就可以监听该实例的状态改变事件onreadystatechange
,它会在 XHR 实例的readyState
的值改变时触发回调函数。
XHR.onreadystatechange = function () { }
然后我们就可以使用open
方法初始化一个请求和send
方法发送 HTTP 请求。
XHR.open('GET', 'http://q.com')// open 方法一共有 5 个参数,method, url, async, user, password 后三个可选。// async 表示这次是否异步请求,默认是 trueXHR.send()// send 方法接受一个可选参数 请求主体。// 参数可以是 FormData, FormData, ArrayBuffer, Document, 序列化字符串
如果是post
方法,就要在send
之前设置请求头的Content-Type
。
httpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')// 它接受两个参数 header 和 value
然后我们就要处理服务器返回的数据,回到onreadystatechange
函数。它监听readyState
属性的变化,而它一共有 5 个值。
0
表示 请求还未初始化,尚未调用 open() 方法。1
表示 已建立服务器链接,open() 方法已经被调用。2
表示 请求已接受,send() 方法已经被调用,并且头部和状态已经可获得。3
表示 正在处理请求,下载中; responseText 属性已经包含部分数据。4
表示 完成,下载操作已完成。我们还需要关心status
属性它也是只读属性,它是这次响应中的 HTTP 数字状态码。在请求之前和 XMLHttpRequest 出错时它为0
。
responseText
属性是实际的数据,它是字符串,如果相应是 JSON 格式,需要用 JSON 的 parse 处理。
XHR.onreadystatechange = function () { if (XHR.readyState === 4 && XHR.status === 200) { console.log(JSON.parse(XHR.responseText))
}
}
如果服务器返回的是 XML, 我们可以用responseXML
属性获得数据。
// 如果已指明,responseType 必须是空字符串或 "docuemnt" XHR.responseType = 'document';// overrideMimeType() 用来强制解析 response 为 XMLXHR.overrideMimeType('text/xml');// --------------var root = XHR.responseXML.getElementsByTagName('root').item(0)
responseType
属性是一个枚举类型的属性,返回响应数据的类型。
withCredentials
属性是一个Boolean类型,它指示了是否该使用类似cookies,authorization headers(头部授权)或者TLS客户端证书这一类资格证书来创建一个跨站点访问控制请求。
(在IE中,超时属性可能只能在调用 open() 方法之后且在调用 send() 方法之前设置)
abort
方法用来终止请求
getAllResponseHeaders
方法返回所有的响应头
getResponseHeader(name)
方法返回包含指定头文本的字符串
XMLHttpRequset 2 增加了一些新功能。比如能发送FormData
。
超时时间
timeout
属性是超时时间,单位毫秒。当超时发生时他会触发ontimeout
回调函数。
xhr.open('GET', '/server')
xhr.timeout = 2000
xhr.ontimeout = function (e) {}
xhr.send(null);
还有 6 个进度事件。
loadstart
在收到响应的第一个字节触发progress
在接收期间不断触发error
发生错误abort
调用abort方法而终止load
接收到完整数据loadend
在通信完成或abort error load事件后触发有load
事件就不用readystatechange
事件和读取readyState
属性。
xhr.addEventListener("progress", updateProgress, false);
xhr.addEventListener("load", transferComplete, false);
xhr.addEventListener("error", transferFailed, false);
xhr.addEventListener("abort", transferCanceled, false);function updateProgress(event) { if (event.lengthComputable) { console.log(`${event.position} / ${event.totalSize}`)
}
}
其中progress
的事件对象多了三个属性。
lengthComputable
布尔值 表示进度信息是否可用position
已经接收到的字节数totalSize
根据Content-Length预期的字节数同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。
当前网址(http://news.a.com)和请求网址
https://news.a.com
不同协议http://news.a.com:8080
不同端口http://home.a.com
不同域名时就不是同源。
为了使 ajax 可以从不同的网址获取数据。
我们可以使用跨域资源共享(CORS)来解决问题。
在发送请求时会有个Origin
头表示请求页面的源信息, 如果服务器返回的Access-Control-Allow-Origin
中有相同的源信息或是*
那么就可以跨域请求信息,请求和响应都不包含cookie
。
CORS通过Preflighted Requests
透明服务器验证机制支持使用自定义头部、get和post之外的方法,不同类型的主题内容。
这种请求已OPTIONS方法发送,下面是它发送的头信息:
Origin
源
Access-Control-Request-Method
请求自身使用的方法
Access-Control-Request-Headers
自定义头部信息,用逗号分隔
发送请求后,服务器来决定是否允许,服务器会发送如下信息与浏览器沟通:
Access-Control-Allow-Origin
允许的源
Access-Control-Allow-Methods
允许的方法,逗号分隔
Access-Control-Allow-Headers
允许的头部,逗号分隔
Access-Control-Allow-Max-Age
Preflight请求缓存的时间(秒)
默认情况下跨域不提供cookie、HTTP认证、SSL证明,通过withCredentials
属性设置为true
可以指定某个请求因该发送凭据。 服务器如果接收请求会返回Access-Control-Allow-Credentials
为true
的头信息。
还有一种方法是使用JSONP
。
jsonp
方法主要是创建script
标签来获得数据,一般通过请求后面跟?callback=fn 回掉函数来获取数据。
Fetch 是网络请求的一个更好的替代方法。相比于 XMLHttpRequest,Fetch 写法更简单,功能更强大。
fetch('http://a.com')
.then(function(response) { if (response.ok) { return response.json();
} throw new Error('err')
})
.then(function(myJson) { console.log(myJson);
})
.catch(err => { console.log(err)
})
fetch 函数接受两个参数,返回一个 Promise 对象 。
第一个参数是 URL 或 Request 对象。第二个参数是可选一个配置项对象。
{ method: 'GET', // 请求方法
headers: { 'user-agent': 'Mozilla/4.0 MDN Example', 'content-type': 'application/json'
}, // 头信息
body: JSON.stringify({data: 1}), // 请求的 body 信息,Blob, FormData 等
mode: 'cors', // 请求的模式,cors、 no-cors 或 same-origin
credentials: 'include', // omit、same-origin 或 include。为了在当前域名内自动发送 cookie, 必须提供这个选项
cache: 'no-cache', // default 、 no-store 、 reload 、 no-cache 、 force-cache 或者 only-if-cached
redirect: 'follow', // 可用的 redirect 模式: follow (自动重定向), error (如果产生重定向将自动终止并且抛出一个错误), 或者 manual (手动处理重定向).
referrer: 'no-referrer', // no-referrer、client或一个 URL。默认是 client。
referrerPolicy: 'no-referrer', // 指定 referer HTTP头
integrity: 'sha256-BpfBw7ivV8q2jLiT13fxDYAe2tJllusRSZ273h2nFSE=', // 包括请求的 subresource integrity 值}
then 的回调函数接受一个 Response 对象。Response 实现了 Body(代表响应/请求的正文,允许你声明其内容类型是什么以及应该如何处理。)
它有 9 个属性。
type
只读 包含Response的类型 (例如, basic, cors)url
只读 包含Response的URLuseFinalURL
包含了一个布尔值来标示这是否是该Response的最终URLstatus
只读 包含Response的状态码ok
只读 包含了一个布尔值来标示该Response成功(状态码200-299)edirected
只读 表示该Response是否来自一个重定向,如果是的话,它的URL列表将会有多个statusText
只读 包含了与该Response状态码一致的状态信息headers
只读 包含此Response所关联的Headers 对象bodyUsed
Body 只读 包含了一个布尔值来标示该Response是否读取过Body8 个方法
clone
创建一个Response对象的克隆error
返回一个绑定了网络错误的新的Response对象redirect(url, status)
用另一个URL创建一个新的 responseBody(都返回一个 Promise 实例)
arrayBuffer
接受一个 Response 流, 并等待其读取完成. 并 resolve 一个 ArrayBuffer 对象blob
blob()方法使用一个 Response 流,并将其读取完成formData
将 Response 对象中的所承载的数据流读取并封装成为一个对象json
使用一个 Response 流,并将其读取完成。解析结果是将文本体解析为 JSONtext
提供了一个可供读取的"返回流", 它返回一个包含USVString对象,编码为UTF-8WebSockets 是一种先进的技术。它可以在用户的浏览器和服务器之间打开双工、双向通讯会话。
WebSocket 构造函数,接受两个参数,url 和 protocols(可选)。
url 以 ws://
或 wss://
(加密)开头
protocols 是 单协议字符串或者包含协议字符串的数组。这些字符串用于指定子协议,这样单个服务器可以实现多个WebSocket子协议(例如,您可能希望一台服务器能够根据指定的协议处理不同类型的交互)protocol)。如果不指定协议字符串,则假定为空字符串。
var s = new WebSocket('ws://www.a.com/s.php') // 必须传入绝对URL,可以是任何网站s.readyState // 0 建立连接 1 已经建立 2 正在关闭 3 连接已关闭或者没有链接成功s.send('hello') // 发送的数据必须是纯文本s.onopen = function (){ console.log('成功建立连接时触发')
}
s.onerror = function () { console.log('发生错误,连接不能持续时')
}
s.onmessage = function (event) { // 当接收到消息时
console.log(event.data) // 数据是纯字符}
s.close() // 关闭连接s.onclose = function (event) { /*
* event.wasClean 是否明确的关闭
* event.code 服务器返回的数值状态码
* event.reason 字符串,服务器返回的消息
*/
console.log('连接关闭时')
}
一共有 10 个属性
binaryType
返回websocket连接所传输二进制数据的类型(blob, arraybuffer)bufferedAmount
只读 返回已经被send()方法放入队列中但还没有被发送到网络中的数据的字节数。一旦队列中的所有数据被发送至网络,则该属性值将被重置为0。但是,若在发送过程中连接被关闭,则属性值不会重置为0。extensions
只读 返回服务器选择的扩展名。这当前只是空字符串或连接协商的扩展列表onclose
用于指定连接失败后的回调函数onmessage
用于指定当从服务器接受到信息时的回调函数onopen
用于指定连接成功后的回调函数protocol
只读 服务器选择的下属协议readyState
只读 当前的链接状态url
只读 WebSocket 的绝对路径2 个方法
close(code, reason)
数字状态码 可选 默认 1005和一个可选的类可读的字符串,它解释了连接关闭的原因。send(data)
向服务器发送数据(ArrayBuffer,Blob等)