Ajax
1了解AJAX
AJAX: Asynchronous Javascript And Xml,Ajax技术的核心是XMLHttpRequest对象(简称XHR),这是由微软首先引入的一个特性,其他浏览器提供商后来都提供了相同的实现。
1.1 ajax的起源
最早出现在2005年的google搜索建议。
1.2 ajax的优点
1.增加速度:减轻服务器的负担,按需加载数据,最大程度的减少冗余请求。
2.改善的用户体验:局部刷新页面,减少用户等待时间,带来更好的用户体验。
3.页面和数据分离:前后端分离,操作更灵活,后期维护更方便。
1.3后端语言与服务器配置
1 php + Apache + mySQL
2 NodeJS + MongoDB
3 Java + tomcat + Oracle
3 .NET + IIS + SQL Server
2 AJAX请求步骤
1.创建请求对象,返回一个异步请求对象。
var xhr = new XMLHttpRequest();
2.处理服务器返回数据。
xhr.onreadystatechange = function(){
//因为还需判定响应的http状态,所以需要对status返回的数据进行判定
if(xhr.readyState == 4 && (xhr.status === 200 || xhr.status === 304)) {
alert(xhr.responseText);
}
}
3.设置请求参数,建立与服务器连接。
xhr.open("get", "http://localhost/api/ajaxtest", true);
4.向服务器发送请求。
xhr.send(null);
3 XMLHttpRequest对象属性方法
3.1 open(type,url,async):建立与服务器链接
1. type:请求的类型 (’get’, ‘post’…) 。
2. url:数据请求的地址(API地址),一般由后端开发人员提供:
2.1当前页面访问地址,API地址两者一定要同域;
2.2同域:协议,域名,端口三者一致(同源策略)。
3. async:是否异步发送请求(true,false),默认为true:
3.1 同步:按步骤顺序执行,前面的代码执行完后,后面的代码才会执行
做完前一件事情, 才能下一件事情(排队);
3.2异步:与其他操作同时执行,也叫并发(图片加载,ajax请求)。
3.2 send(data):向服务器发送请求
1. data:可选参数,post请求时才生效,表示发请求时传送的数据字符串。
xhr.send('size=20&type=music');
在某些浏览器中,如果不需要通过请求主体发送数据,则必须传入null
2. get请求的数据写在api地址后。
request.open("get", "http://localhost/api/getdata.php?type=get&qty=10", true);
3.3 setRequestHeader(key,val):设置请求头
设置请求头必须在open方法调用后设置。
利用请求头设置POST提交数据格式:
xhr.setRequestHeader(‘content-type’,”application/x-www-form-urlencoded”);
3.4 readyState
**在请求收到服务器的响应后,响应的数据会自动填充xhr 对象的属性,相关的属性简介如下:
· 0 - (未初始化)尚未调用open()方法。
· 1 - (启动)已经调用open()方法,但尚未调用send()方法。
· 2 - (发送)send()方法执行完成,但尚未接收到响应。
· 3 - (接收)已经接收到部分响应数据。
· 4 - (完成)响应内容解析完成,可以在客户端调用了
只要readyState 属性的值由一个值变成另一个值,都会触发一次readystatechange 事件。必须在调用open()之前指定onreadystatechange事件处理程序才能确保跨浏览器兼容性。
3.5 responseText
保存服务器返回的数据(从服务器返回的数据是“字符串”)。
3.6 Status 响应的HTTP状态
· 200(OK):服务器成功返回了页面;
· 304(Not Modified):数据与服务器相同,不需要重服务器请求(直接使用缓存的数据);
· 400(Bad Request):语法错误导致服务器不识别;
· 401(Unauthorized):请求需要用户认证;
· 404(Not found):请求地址不存在;
· 500(Internal Server Error):服务器出错或无响应;
· 503(ServiceUnavailable):由于服务器过载或维护导致无法完成请求。
3.7 statusText:HTTP状态码的说明
3.8 XMLHttpRequest的兼容性
var req = null;
try{
req = new XMLHttpRequest();
}catch(err){
// ie低版本浏览有多种异步请求的实现
try{
req = new ActiveXObject("Msxml2.XMLHTTP");
}catch(err){
try{
req = new ActiveXObject("Microsoft.XMLHTTP");
}catch(err){
alert('你的浏览器太low了,这个世界不适合你');
}
}
}
//其中try..catch,try..catch中的catch可以嵌套新的try..catch
var sum = 100;
try{
// 尝试执行这里的代码
// 如果成功,则继续执行后面的代码
console.log('try');
sum();
}catch(error){
// 如果报错,则执行catch中的代码(并附带错误信息,但不会影响代码的执行)
console.log(sum);
console.log(error);
}
4 JSON数据的应用
4.1 xml数据(了解)
<person>
<id>4564523626256562</id>
<name>张三</name>
</person>
4.2 JSON数据(JSON字符串)
{"id" : 21465461461461, "name": "张三"},[{"id" : 21465461461461, "name": "张三"}]
4.2.1 JSON对象(ES5)
· JSON.parse(); //把JSON字符串转成JSON对象(js对象/数组)。
· JSON.stringify(); //把JSON对象转成JSON字符串。
4.2.2 eval方法转换
eval("("+json字符串+")");
它的作用是,将一个普通的json格式的字符串,转换成Json格式的对象。例如:
var list = eval("("+request.responseText+")");
5 Ajax跨域解决方法
5.1 JSONP
JSONP是JSON with padding(填充式JSON或参数式JSON)的简写。JSONP是一种可以绕过浏览器的安全限制,从不同的域请求数据的方法。使用JSONP需要服务器端提供必要的支持。
callback({ "name": "Nicholas" });//此代码在服务器生成
JSONP 由两部分组成:回调函数和数据。回调函数是当响应到来时应该在页面中调用的函数。
但JSONP只支持GET方式,不支持POST方式。
5.1.1 JSONP请求原理
JSONP的原理是通过script标签发起一个GET请求来取代XHR请求。
jsonp请求不是ajax请求,是利用script标签能请求跨域的原理来获取其他服务器的数据。
JSONP请求需要服务端的支持。
5.1.2 JSONP请求步骤
1.预定义全局函数getData
function getData(data){
console.log(data);
}
PS:预定义函数必须为全局函数。
在局部作用域中想定义全局函数,可以用:window.getData = function(){};
2.生成script标签,请求服务器地址,并附带函数名
<script src="http://localhost:1000/json.php?callback=getData">< /script>
通常我们用DOM节点的方式生成script标签,写入src并插入到head中:
// 创建一个script标签
var script = document.createElement('script');
script.src = 'http://localhost:1000/jsonp.php?callback=myData';//myData({})
// 把生成的script标签写入页面
document.head.appendChild(script);
3.服务器返回js文件(js文件里面包含我们预先定义的函数执行)
请求成功后,得到的js代码为:
getData({name: '王大锤',age: 30,sex: '男',married:false})
当这个函数成功调用时,就可以执行预定义函数里的代码(处理返回的数据)。
5.2 CORS
CORS是一个W3C标准,全称是”跨域资源共享”(Cross-origin resource sharing),它允许浏览器向跨源服务器发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。
CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。
5.2.1 Access-Control-Allow-Origin
该字段是必须的。需要在后端响应头添加词字段,值要么是一个*,表示接受任意域名的请求,要么指定一个域名http://localhost,如想指定若干个请使用判断语句,php代码如下:
$allow_origin = array(
'http://www.client.com',
'http://www.client2.com'
);
if(in_array($origin, $allow_origin)){
header('Access-Control-Allow-Origin:'.$origin);
}
5.2.2 Access-Control-Allow-Methods
5.2.3 Access-Control-Allow-Headers
header('Access-Control-Allow-Methods:POST');
header('Access-Control-Allow-Headers:x-requested-with,content-type');
5.3 服务器代理
后端不存在跨域问题,所以可以利用后端间接获取其他网站的数据。
例如,利用爬虫获取远程JSON数据:
原理:获取页面所有内容,并利用正则匹配所需内容。
· file_get_contents($url);
· preg_match_all($reg,$str,$res);
· preg_match($reg,$str,$res);
6 Promise
Promise是一个构造函数,所谓的Promise对象,就是通过new Promise()实例化得到的对象,用来传递异步操作的消息。它代表了某个未来才会知道结果的事件(通常是一个异步操作),并且这个事件提供统一的 API,可供进一步处理。
有了Promise对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。
6.1 Promise的三种状态
· Pending(未完成)可以理解为Promise对象实例创建时候的初始状态。
· Resolved(成功) 可以理解为成功的状态。
· Rejected(失败) 可以理解为失败的状态。
6.2 Promise的方法
6.2.1静态方法
6.2.1.1 Promise.resolve()
将现有对象转为Promise对象,并将该对象的状态改成resolved。
var p = Promise.resolve('foo');
// 等价于
var p = new Promise(resolve => resolve('foo'));
6.2.1.2 Promise.reject()
返回一个新的 Promise 实例,该实例的状态为rejected。
6.2.1.3 Promise.all([p1,p2,p3...])
将多个Promise实例,包装成一个新的Promise实例。所有参数中的promise状态都为resolved是,新的promise状态才为resolved;只要p1、p2、p3..之中有一个被rejected,新的promise的状态就变成rejected。
6.2.1.4 Promise.race([p1,p2,p3...])
// 竞速,完成一个即可。
6.2.2原型方法
6.2.2.1 Promise.prototype.then(successFN[,failFn])
Promise实例生成以后,可以用then方法分别指定Resolved状态和Rejected状态的回调函数。并根据Promise对象的状态来确定执行的操作: 1.resolved时执行第一个函数successFn;2.rejected时执行第二个函数failFn。
Promise有多个then嵌套使用时,可使用链式调用。
var p = new Promise(function(resolve,reject){
// reject();//Pending=>Reject()
resolve(100)
});
p.then(function(data){
console.log('success',data);
return data*2; //链式调用,必须要return,不然后面的data会undefined
},function(){
console.log('失败');
//当then中的failFn和后面的catch同时存在时,执行then中的failFn
}).catch(function(){
console.log('fail');
}).then(function(data){
console.log('成功',data);
return 'laoxie';
}).then(function(data){
console.log('很成功',data);
//因为return为p2,5s后执行p2的resolve();如果return的是data,则立刻执行下一个then
var p2 = new Promise(function(resolve,reject){
setTimeout(function(){
resolve('lemon');
},5000);
});
return p2;
}).then(function(data){
console.log('非常成功',data);
})
6.2.2.2 Promise.prototype.catch(failFn)
6.3 Promise的使用
var p = new Promise(function(resolve, reject){
//ajax请求
ajax({
url:'xxx.php',
success:function(data){
resolve(data)
},
fail:function(){
reject('请求失败')
}
});
});
//指定Resolved状态和Rejected状态的回调函数
//一般用于处理数据
p.then(function(res){
//这里得到resolve传过来的数据
},function(err){
//这里得到reject传过来的数据
})
Promise的构造函数接收一个回调函数作为参数,并且传入两个参数: resolve,reject,分别表示异步操作执行成功和失败后的回调函数:
1.调用resolve方法将Promise对象的状态从「未完成」变为「成功」(从 pending 变为 resolved);
2.调用reject方法将Promise对象的状态从「未完成」变为「失败」(从 pending 变为 rejected);
3.如果调用resolve函数和reject函数时带有参数,那么它们的参数会被传递给回调函数。
6.4 Promise的应用
加载图片,获取图片信息(宽高):
var preloadImage = function (path) {
return new Promise(function (resolve, reject) {
var image = new Image();
image.onload = ()=>{
resolve(image);
}
image.onerror = reject;
image.src = path;
});
};
//使用
preloadImage('http://image.baidu.com/xxx.jpg').then((img)=>{
document.body.appendChild(img);
console.log(img.offsetWidth,img.offsetHeight);
})
7 API
7.1 服务器API
7.1.1向服务器请求数据
接口地址: 例如:api/ajaxtest.php 。
接口描述:返回一段字符串,无特殊功能。
7.1.2判断用户名是否已被注册
接口地址: 例如: api/checkname?regname=xiejinrong 。
接口描述:该地址验证所提交的用户名是否存在,如果已存在,返回字符串no,不存在返回yes。
参数说明:regname:注册用户名,必填。
7.1.3微博消息获取
接口地址: 例如: api/weibo.php 。
接口描述:返回包含多条微博记录的json数据。
7.1.4分页获取数据
接口地址: 例如:api/football.php 。
接口描述:该地址请求多条微博信息,分页获取,pageNo指定获取第几页的数据。
参数说明:
pageNo:当前分页,默认1;
qty:每页显示数量,默认10。
7.1.5聊天室
获取本机ip地址:api/getip.php;
获取信息:api/chat.php?type=query;
发送信息:api/chat.php?type=send&sender=xiejinrong&msg=hello 。
7.1.6利用jsonp获取远程数据
接口地址:api/jsonp.php;
接口描述:jsonp跨域解决方案。
例如:
利用jsonp实现百度搜索关键字建议
https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?json=1&cb=getData&wd=html5
7.1.7利用cors获取远程数据
接口地址:api/cors.php
接口描述:CORS跨域解决方案
例如:
利用CORS加载天气
接口地址:http://wthrcdn.etouch.cn/weather_mini?city=北京
接口描述:通过城市名字获得天气数据,json数据