1、XMLHttpRequest
XHR英文全名XmlHttpRequest,中文可以解释为可扩展超文本传输请求。Xml可扩展标记语言,Http超文本传输协议,Request请求。XMLHttpRequest对象可以在不向服务器提交整个页面的情况下,实现局部更新网页。当页面全部加载完毕后,客户端通过该对象向服务器请求数据,服务器端接受数据并处理后,向客户端反馈数据。 XMLHttpRequest 对象提供了对 HTTP 协议的完全的访问,包括做出 POST 和 HEAD 请求以及普通的 GET 请求的能力。XMLHttpRequest 可以同步或异步返回 Web 服务器的响应,并且能以文本或者一个 DOM 文档形式返回内容。尽管名为 XMLHttpRequest,它并不限于和 XML 文档一起使用:它可以接收任何形式的文本文档。XMLHttpRequest 对象是名为 AJAX 的 Web 应用程序架构的一项关键功能。
var xhr = new XMLHttpRequest() xhr.open("GET", "/api", false) xhr.onreadystatechange = function () { // 这里的函数异步执行,可参考 JS 基础中的异步模块 if (xhr.readyState == 4) { if (xhr.status == 200) { alert(xhr.responseText) } } } xhr.send(null)
2、状态码说明
1)readyState
xhr.readyState 的状态码说明
- 0 - (未初始化)还没有调用send()方法
- 1 -(载入)已调用send()方法,正在发送请求
- 2 -(载入完成)send()方法执行完成,已经接收到全部响应内容
- 3 -(交互)正在解析响应内容
- 4 -(完成)响应内容解析完成,可以在客户端调用了
2)status
http 状态码有 `2xx` `3xx` `4xx` `5xx` 这几种,比较常用的有以下几种
- 200 正常
- 404 找不到资源
- 5xx 服务器端出错了
3、跨域
浏览器中有“同源策略”,协议、域名、端口,只有全部相同才算同源,才能相互访问。
html中几个标签能逃避过同源策略——`<script src="xxx">`、`<img src="xxxx"/>`、`<link href="xxxx">`,这俩标签的 src/href 可以加载其他域的资源,不受同源策略限制。
- `<img>`可以做打点统计,因为统计方并不一定是同域的除了能跨域之外,`<img>`几乎没有浏览器兼容问题,它是一个非常古老的标签。
- `<script>`和`<link>`可以使用CDN,CDN基本都是其他域的链接。
- 另外`<script>`还可以实现JSONP,能获取其他域接口的信息
4、JSONP
访问`http://coding.m.imooc.com/classindex.html`的时候,服务器端就一定有一个`classindex.html`文件吗?—— 不一定,服务器可以拿到这个请求,然后动态生成一个文件,然后返回。
同理,`<script src="http://coding.m.imooc.com/api.js">`也不一定加载一个服务器端的静态文件,服务器也可以动态生成文件并返回。
在自己的页面这样定义:
<script> window.callback = function (data) { // 这是我们跨域得到信息 console.log(data) } </script>
然后服务器提供了一个`http://coding.m.com/api.js`,内容如下(服务器可动态生成内容)
callback({x:100, y:200})
最后我们在页面中加入`<script src="http://coding.m.com/api.js"></script>`,那么这个js加载之后,就会执行内容,我们就得到内容了
5、服务器端设置 http header
服务器端推崇的跨域解决方案是这一种,比 JSONP 简单许多。
response.setHeader("Access-Control-Allow-Origin", "http://localhost:8011"); // 第二个参数填写允许跨域的域名称,不建议直接写 "*" response.setHeader("Access-Control-Allow-Headers", "X-Requested-With"); response.setHeader("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS"); // 接收跨域的cookie response.setHeader("Access-Control-Allow-Credentials", "true");