ES5进阶-AJAX
阅读 (526)一、通信原理
-
URL
统一资源定位符,是互联网上资源的地址
-
协议
该URL的协议部分为"http:",这代表网页使用的是HTTP协议。在Internet中可以使用多种协议,如HTTP,HTTPS,FTP等等,本例中使用的是HTTP协议。在"HTTP"后面的“//”为分隔符
-
域名
该URL的域名部分为"www.sunck.wang"。一个URL中,也可以使用IP地址作为域名使用
-
端口
跟在域名后面的是端口,域名和端口之间使用":"作为分隔符。端口不是一个URL必须的部分,如果省略端口部分,将采用默认端口(HTTP为80,HTTPS为443)
-
虚拟目录
从域名后的第一个“/”开始到最后一个"/“为止,是虚拟目录部分。虚拟目录也不是一个URL必须的部分,本例中的虚拟目录是”/news/"
-
文件名
从域名后的最后一个"/“开始到”?“为止,是文件名部分,如果没有”?",则是从域名后的最后一个"/“开始到”#“为止,是文件部分,如果没有”?“和”#",那么从域名后的最后一个"/“开始到结束,都是文件名部分。本例中的文件名是"index.asp”。文件名部分也不是一个URL必须的部分,如果省略该部分,则使用默认的文件名
-
参数
从"?“开始到”#“为止之间的部分为参数部分,又称搜索部分、查询部分。本例中的参数部分为“ID=34256&page=1”。参数可以允许有多个参数,参数与参数之间用”&"作为分隔符
-
锚
从"#"开始到最后,都是锚部分,本例中的锚部分是“name”,锚部分也不是一个URL必须的部分
-
同源策略
要求动态内容(如JavaScript)只能阅读与之同源的那些HTTP应答和cookies,而不能阅读来自非同源的内容
问答:
-
我们是如何通过浏览器访问页面的?(了解内容B/S模式)
思考:当我们打开浏览器,在浏览器的地址栏中输入URL地址"http://www.sunck.wang:8080/WebDemo1/1.html"去访问服务器上的1.html这个web资源的过程中,浏览器和服务器都做了神马操作呢,我们是怎么在浏览器里面看到1.html这个web资源里面的内容的呢?
浏览器和服务器做了以下几个操作:
- 浏览器根据主机名"www.sunck.wang"去操作系统的Hosts文件中查找主机名对应的IP地址
- 浏览器如果在操作系统的Hosts文件中没有找到对应的IP地址,就去互联网上的DNS服务器上查找"www.sunck.wang"这台主机对应的IP地址
- 浏览器查找到"www.sunck.wang"这台主机对应的IP地址后,就使用IP地址连接到Web服务器
- 浏览器连接到web服务器后,就使用http协议向服务器发送请求,发送请求的过程中,浏览器会向Web服务器以Stream(流)的形式传输数据,告诉Web服务器要访问服务器里面的哪个Web应用下的Web资源
- 浏览器做完上面4步工作后,就开始等待,等待Web服务器把自己想要访问的1.html这个Web资源传输给它
- 服务器接收到浏览器传输的数据后,开始解析接收到的数据,服务器解析"GET /WebDemo1/1.html "里面的内容时知道客户端浏览器要访问的是WebDemo1应用里面的1.html这个Web资源,然后服务器就去读取1.html这个Web资源里面的内容,将读到的内容再以Stream(流)的形式传输给浏览器
- 浏览器拿到服务器传输给它的数据之后,就可以把数据展现给用户看了
-
早期页面交互
- 现在页面交互
-
同步交互
提交请求–>等待服务器处理–>服务器返回数据,在此期间页面不能进行任何操作(B/S模式)
-
异步交互
请求通过事件触发–>服务器处理(然后可以做其他的事情)–>服务器进行响应(ajax)
-
同步与异步举例
异步:你传输吧,我去忙其他事情了,传完之后告诉我
同步:你传输,我就静静的看你传完之后我在去做其他的事情 -
屌丝与女神
- ajax通信原理
二、Apache服务器安装与使用
-
介绍
- Apache HTTP Server(简称Apache)是Apache软件基金会的一个开放源码的网页服务器,是目前世界上使用最广泛的一种web server,它以跨平台,高效和稳定而闻名,可以运行在几乎所有广泛使用的计算机平台上。Apache的特点是简单、速度快、性能稳定,并可做代理服务器来使用。
- Apache是用C语言开发的基于模块化设计的web应用,总体上看起来代码的可读性高于php代码,它的核心代码并不多,大多数的功能都被分割到各种模块中,各个模块在系统启动时按需载入。
- 支持SSL技术,支持多个虚拟主机。Apache是以进程的Prefork模式(还有基于线程的Worker模式)为基础的结构,进程要比线程消耗更多的系统开支,不太适合于多处理器环境,因此,在一个Apache Web站点扩容时,通常是增加服务器或扩充群集节点而不是增加处理器
-
安装
- 官网下载安装包
- 将安装包拷贝到某个盘下并解压
- 进入Apache24下的conf目录,并打开httpd.conf文件(建议使用sublim打开)
- 修改相应配置后保存关闭配置文件
- 以管理云身份打开黑屏终端
- 进入Apache24下的bin目录
- 执行安装命令[httpd.ext -k install -n “Apache24”]
- 成功提示
-
解决虚拟机443端口问题(不解决Apache服务无法启动)
编辑–>首选项–>共享虚拟机
- 启动Apache服务
-
如果安装出现问题,建议卸载后重新操作
卸载命令:httpd.ext -k uninstall -n “Apache24”
-
使用
- 创建简单界面,放入Apache24下的htdocs目录下
- 浏览器访问
三、ajax实现通信
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>home</title>
</head>
<body>
<button id="btn">发起ajax请求</button>
<script type="text/javascript">
var jsBtn = document.getElementById("btn");
jsBtn.addEventListener("click", function(){
//0、创建xhr对象
var xhr = new XMLHttpRequest();
// console.log(xhr);
xhr.onreadystatechange = myCallBack;
//1、初始化请求
/**
* parameter1:设置请求类型(get或者post)
* parameter2:设置请求url
* parameter3:设置是否异步,true异步,flase同步。默认使用异步
*/
xhr.open("get", "http://192.168.1.13:8090/test.txt", true);
//2、发送请求
/**
* 初始化时使用get时不用传参
* 初始化时使用post传参
*/
xhr.send();
//3、接收返回数据
function myCallBack() {
//3.1判断http响应状态
//200与304状态吗说明请求通信正常
if (xhr.status == 200 || xhr.status == 304) {
if (xhr.readyState == 4) {
//4、处理数据
console.log(xhr.responseText);
}
}
}
console.log("-----------")
}, false);
</script>
</body>
</html>
- XMLHttpRequest对象核心属性
-
on……
触发某种事件后对应的事件处理程序(事件监听器)
onreadystatechange:服务器响应客户端后执行
-
readyState
请求状态
值 说明 0 创建xhr对象 1 初始化请求 2 发送请求 3 接收到响应 4 完成接收数据 -
response
服务器响应的数据
-
responseText
服务器响应的数据(字符串类型)
-
responseType
服务器响应数据的类型
-
responseURL
响应请求的网址
-
responseXML
当返回的数据是(text/xml或application/xml)等类型响应也会存在该字段中
-
status
http响应状态
-
statusText
http状态说明
-
timeout
设置超时时间
-
http响应状态
点击百度百科查看具体说明
四、请求Json文件
-
Json
概念:一种保存数据的格式,可以保存本地的json文件,也可以将json串进行传输,通常将json称为轻量级的传输方式
json文件的基本构成:
结构 说明 {} 代表对象 [] 代表数组 : 代表属性对 , 分隔两个部分
typ说明:
类型 | 说明 |
---|---|
Array | 数组 |
Object | 对象 |
String | 字符串 |
Number | 数字 |
Boolean | 布尔 |
Null | 空 |
-
请求
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>index</title> </head> <body> <button id="btn">发起ajax请求</button> <script type="text/javascript"> var jsBtn = document.getElementById("btn"); jsBtn.addEventListener("click", function(){ var xhr = new XMLHttpRequest(); xhr.onreadystatechange = myCallBack; xhr.open("get", "http://192.168.1.13:8090/caidan.json", true); xhr.send(); function myCallBack() { if (xhr.status == 200 || xhr.status == 304) { if (xhr.readyState == 4) { console.log(xhr.responseText); console.log(typeof xhr.responseText); // 将json字符串转成字面量对象 var jsObj = JSON.parse(xhr.responseText); console.log(jsObj); console.log(typeof jsObj); // 将字面量对象转成json字符串 var jsStr = JSON.stringify(jsObj); console.log(jsStr); console.log(typeof jsStr); } } } console.log("-----------") }, false); </script> </body> </html>
五、常见的HTTP请求方式
方法 | 说明 |
---|---|
GET | 向特定的路径资源发出请求,数据暴露在url中 |
POST | 向指定路径资源提交数据进行处理请求(一般用于上传表单或者文件),数据包含在请求体中 |
DELETE | 请求服务器删除指定的数据 |
PUT | 从客户端向服务器传送的数据取代指定的文档的内容 |
PATCH | 是对 PUT 方法的补充,用来对已知资源进行局部更新 |
HEAD | 类似于 GET 请求,只不过返回的响应中没有具体的内容,用于获取报头 |
OPTIONS | 允许客户端查看服务器的性能 |
TRACE | 回显服务器收到的请求,主要用于测试或诊断 |
CONNECT | HTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器 |
六、GET与POST的区别
-
传参方式
GET的形式把参数拼接在请求路径后面传给服务器
POST把参数进行打包,单独去传输
-
优缺点
GET:速度快,数据小(当不对服务器数据进行更改时建议使用get方式)
POST:速度慢,数据大,安全(当对服务器数据进行更改时建议使用post方式)
说明:从传输的角度来说,他们都是不安全的,因为 HTTP 在网络上是明文传输的,只要在网络节点上捉包,就能完整地获取数据报文,要想安全传输,就只有加密,也就是 HTTPS
-
GET示例
var xhr = new XMLHttpRequest(); xhr.onreadystatechange = myCallBack; xhr.open("get", "http://192.168.1.13:8090/caidan.json?x=1&y=2", true); xhr.send(); function myCallBack() { if (xhr.status == 200 || xhr.status == 304) { if (xhr.readyState == 4) { console.log(xhr.responseText); console.log(typeof xhr.responseText); } } }
-
POST示例
var xhr = new XMLHttpRequest(); xhr.onreadystatechange = myCallBack; xhr.open("post", "http://192.168.1.13:8090/caidan.json", true); xhr.send("{x:1, y:2}"); function myCallBack() { if (xhr.status == 200 || xhr.status == 304) { if (xhr.readyState == 4) { console.log(xhr.responseText); console.log(typeof xhr.responseText); } } }
注意:post 需要你有服务器去处理post请求,get 的话Hbulider里面有一个内置的服务器可以处理,但是post不行
七、xhr兼容性问题
原因:IE低版本浏览器不支持XMLHttpRequest
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<script type="text/javascript">
var xhr = null;
if (typeof XMLHttpRequest != "undefined") {
xhr = new XMLHttpRequest();
} else if (typeof ActiveXObject != "undefined") {
// 低版本的IE浏览器
var versionArr = ["MSXML.XMLHttp.6.0","MSXML.XMLHttp.3.0","MSXML.XMLHttp"];
for (var i = 0; i < versionArr.length; i++){
try{
xhr = new ActiveXObject(versionArr[i]);
break;
} catch(err){
console.log(err);
}
}
if (i == 3){
alert("您的浏览器版本太低,请升级版本!");
}
} else {
alert("您的浏览器版本太低,请升级版本!");
}
xhr.onreadystatechange = myCallBack;
xhr.open("get", "tset.txt", true);
xhr.send();
function myCallBack(){
if (xhr.status == 200 || xhr.status == 304){
if (xhr.readyState == 4){
console.log(xhr.responseText);
}
}
}
</script>
</body>
</html>
八、封装xhr
xhr.js
function MyAjax(method, url, isAsyn, sendParam, callBack){
this.method = method;
this.url = url;
this.isAsyn = isAsyn;
this.sendParam = sendParam;
this.callBack = callBack;
this.xhr = null;
this.createXHR = function(){
if (typeof XMLHttpRequest != "undefined") {
return new XMLHttpRequest();
} else if (typeof ActiveXObject != "undefined") {
var versionArr = ["MSXML.XMLHttp.6.0","MSXML.XMLHttp.3.0","MSXML.XMLHttp"];
for (var i = 0; i < versionArr.length; i++){
try{
return new ActiveXObject(versionArr[i]);
break;
} catch(err){
console.log(err);
}
}
if (i == 3){
alert("您的浏览器版本太低,请升级版本!");
}
} else {
alert("您的浏览器版本太低,请升级版本!");
}
}
this.send = function(){
this.xhr = this.xhr || this.createXHR();
var url = this.url;
if (this.method.toUpperCase() == "GET"){
url += "?";
var temp = "";
for (var i in this.sendParam){
temp += (i + "=" + this.sendParam[i] + "&");
}
url += temp.substr(0, temp.length - 1);
}
this.xhr.open(this.method, url, this.isAsyn);
if (this.method.toUpperCase() == "GET"){
this.xhr.send();
} else {
this.xhr.send(JSON.stringify(this.sendParam));
}
this.xhr.onreadystatechange = this.callBack;
}
}
index.html
function myCallBack() {
if (xhr.xhr.status == 200 || xhr.xhr.status == 304) {
if (xhr.xhr.readyState == 4) {
console.log(xhr.xhr.responseText);
}
}
}
var xhr = new MyAjax("get", "http://127.0.0.1:8848/code/caidanJson.json", true, {x:1, y:2}, myCallBack);
xhr.send();
九、跨域访问
-
何为跨域?
同源策略是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略, 浏览器很容易受到 XSS、CSFR 等攻击。所谓同源是指"协议+域名+端口"三者相同, 即便两个不同的域名指向同一个 ip 地址,也非同源 ,非同源无法访问。访问非同源的链接即为跨域访问
-
请求跨域了,那么请求到底发出去没有?
跨域并不是请求发不出去,请求能发出去,服务端能收到请求并正常返回结果,只是结 果被浏览器拦截了。你可能会疑问明明通过表单的方式可以发起跨域请求,为什么 Ajax 就不会?因为归根结底,跨域是为了阻止用户读取到另一个域名下的内容,Ajax 可以获取响应,浏览器认为这不安全,所以拦截了响应。但是表单并不会获取新的内 容,所以可以发起跨域请求。同时也说明了跨域并不能完全阻止 CSRF,因为请求毕竟 是发出去了
-
特别说明
- 如果是协议和端口造成的跨域问题“前台”是无能为力的
- 在跨域问题上,仅仅是通过“URL 的首部”来识别而不会根据域名对应的 IP 地址 是否相同来判断。“URL 的首部”可以理解为“协议, 域名和端口必须匹配”
-
方式
- jsonp
- cors
- postMessage
- websocket
- Node 中间件代理
- nginx 反向代理
- window.name + iframe
- location.hash + iframe
- document.domain + iframe
-
jsonp实现跨域
原理:利用
script
标签没有跨域限制的漏洞,网页可以得到从其他来源动态产生的 JSON 数据。JSONP 请求一定需要对方的服务器做支持才可以与ajax对比:JSONP 和 AJAX 相同,都是客户端向服务器端发送请求,从服务器端获取数据的方式。但 AJAX 属于同源策略,JSONP 属于非同源策略(跨域请求)
优缺点:JSONP 优点是简单兼容性好,可用于解决主流浏览器的跨域数据访问的问题。缺点是仅支持 get 方法具有局限性,不安全可能会遭受 XSS 攻击
实现流程:
- 声明一个回调函数,其函数名(如 show)当做参数值,要传递给跨域请求数据的服务器,函数形参为要获取目标数据(服务器返回的 data)
- 创建一个
script
标签,把那个跨域的 API 数据接口地址,赋值给 script 的 src,还要在这个地址中向服务器传递该函数名(可以通过问号传参:?callback=show) - 服务器接收到请求后,需要进行特殊的处理:把传递进来的函数名和它需要给你的数据拼接成一个字符串,例如:传递进去的函数名是 show,它准备好的数据是
show('我不爱你')
- 最后服务器把准备的数据通过 HTTP 协议返回给客户端,客户端再调用执行之前声明的回调函数(show),对返回的数据进行操作
实现代码:
function show(data){ console.log("-----------"); console.log(data); } //动态创建一个script标签 var JSONP = document.createElement("script"); JSONP.type = "text/javascript"; //script的src属性可以跨域 JSONP.src = "http://crossdomain.com/jsonServerResponse?callback=show"; document.getElementsByTagName("head")[0].appendChild(JSONP);
-
总结
- CORS 支持所有类型的 HTTP 请求,是跨域 HTTP 请求的根本解决方案
- JSONP 只支持 GET 请求,JSONP 的优势在于支持老式浏览器,以及可以向不支持 CORS 的网站请求数据。
- 不管是 Node 中间件代理还是 nginx 反向代理,主要是通过同源策略对服务器不加限制。
- 日常工作中,用得比较多的跨域方案是 cors 和 nginx 反向代理