ajax
ajax
1.什么是ajax
asynchronous javascript and xml,是一种异步加载数据的方式,可以使用ajax实现页面的局部刷新。
2.如何使用ajax
ajax的核心对象是XMLHttpRequest
1.get:向服务器取得数据,根据服务器的实现不同,get,post也可以实现相同的功能,当然也都能向服务器传送取得数据,和rxe标准是有冲突的,不建议这样使用。
get数据放到了URL中,因为放在了URL中,get发送的数据是有限制的,2048个字节,会产生一个安全性的隐患。
2.post:向服务器发送数据,POST请求放到了请求体中,会用https对包进行加密,安全性比较好
1.创建AJAX
var xhr = new XMLHttpRequest();
4.监听请求
xhr.onreadystatechange = function(){ //当xhr的readystate属性发生了改变,则触发事件。 //readystate状态, //0表示=》xhr对象已经创建,但是没有初始化,相当于new了一个对象,但是没有open(); //1表示,xhr已经调用open(), //2表示,xhr已经发出了ajax请求,调用了send()的时候。 //3表示,数据已经返回了部分 //4表示,数据已经全部返回 if(xhr.readyState !== 4){ return; } if(xhr.status >= 200 && xhr.status <= 300){ //数据存放在了xhr.responseText的属性中(String) document.querySelector("h1").innerHTML = xhr.responseText; }else{ console.error("请求出错"); } }
2.打开这个对象
xhr.open("get","../js/test.txt",true);//true代表异步方式,false就是同步的方式发送
3.发送请求
xhr.send();
post方法
1.创建一个xhr的对象(post)
var xhr = new XMLHttpRequest();
5.监听数据是否返回。
xhr.onreadystatechange = function(){ if(xhr.readyState !== 4){ return; } if(xhr.status >= 200 && xhr.status <= 300){ //我们需要一个JOSN的对象, var resp = JSON.parse(xhr.responseText); if(resp.result){ console.log("ok"); }else{ console.log("error"); } }else{ console.error("请求出错"); } }
2.配置这个对象。post的数据放入了body中,就如同传入一个参数被send当做一个body的内容发送。
xhr.open("post","../js/test.php",true);
3.为了让服务器理解表单格式,设立表单头和方法
xhr.setRequestHeader("content","application/x-www-form-urlencoded");
4.发送表单数据
xhr.send("user=gap&password=123456");
3.JSON
1.Javascript Object Natation,是一种轻量级的数据交换格式。是由ECMA定义的,function和undefined是不能作为值传递的。
数据格式:
Object:{"name":"john","age":18}; //对象形式
arr:["john",18]; //数组形式
value:string,number,object,array,true false,null
2.JS的对象子集,于JS进行无缝对接。
3.JSON数据与JS对象的转换。
JSON:JS: JSON.parse(data);
JS:JSON: JSON.stringify(JSObj);
1.回调地狱,promise
1.回调地狱
x= getDate(); y = getMoreDate(); z = getMoreDate(); //如果当x还在数据传输中,没有完成数据返回,就被y调用,就会出现错误。 //如果使用一层一层的回调,会导致回调层级特别深,开发维护成本高,所以在es6中提出了promise对象。 getDate(function(x){ getMoreDate(x,function(y){ getMoreDate(y,function(z){ process z; }) }) })
2.promise
1.可以通过promise构造函数创建一个对象,可以解决回调地狱,它不仅支持一个回调,还支持回调与回调之间的连续调用。
2.这个promise实际上有三种状态,pending等待,fulfill满足了条件的返回状态,reject延时对象,没有满足
3.promise的构造函数有一个参数,是一个回调,他接受两个参数,这两个参数都能改变promise的状态,第一个参数可以从pending切换到fulfill,第二个参数可以将pending切换到reject状态。
var prom = new Promise(function(resolve,reject){ setTimeout(function(){ var num = Math.floor(Math.random() * 100); if(num % 2 === 0){ resolve(num); }else{ reject(num); } },3000) }); //使用promise的一个回调,成功的时候会调用then函数,失败的时候调用catch函数。 prom.then(function(num){ console.log("resolve:" + num); }).catch(function(num){ console.log("reject:" + num); });
3.Ajax的依赖调用。
1例子,有一篇文章,第一次取得第一段文章,第二次取得第二段文章,第三次取得第三段文章,第四次取得第四段文章。
意味着取得有顺序,第一次返回之前,不能运行第二次。这和回调地狱有点相似,可以用promise来解决这种链式调用,链式调用过深难以维护。这里用jquery来演示
var article = ""; $.get("../para/p1.txt",function(p1){ article += p1 + "<br />"; $.get("../para/p2.txt",function(p2){ article += p2 + "<br />"; $.get("../para/p3.txt",function(p3){ article += p3 + "<br />"; $.get("../para/p4.txt",function(p4){ article += p4 + "<br />"; $("h1").html(article); }) }) }) })
4.Promise解决Ajax的依赖调用。
function getDate1(){ return new Promise(function(resolve,reject){ $.get("../para/p1.txt",function(p1){ resolve(p1); }) }) } function getDate2(){ return new Promise(function(resolve,reject){ $.get("../para/p2.txt",function(p2){ resolve(p2); }) }) } function getDate3(){ return new Promise(function(resolve,reject){ $.get("../para/p3.txt",function(p3){ resolve(p3); }) }) } function getDate4(){ return new Promise(function(resolve,reject){ $.get("../para/p4.txt",function(p4){ resolve(p4); }) }) } var article = ""; //getDate返回了一个promise对象,所以可以调用then方法 getDate1().then(function(p1){ article += p1 + "<br />"; return getDate2(); }).then(function(p2){ article += p2 + "<br />"; return getDate3(); }).then(function(p3){ article += p3 + "<br />"; return getDate4(); }).then(function(p4){ article += p4 + "<br />"; $("h1").html(article); });
promise的all()
promise如果原生的使用是比较难用的,这里promise.all()就是promise的精华,有了这个,才能真正的实现promise的用途,比如给个数组
promise.all([
p1,
p2,
p3
]).then();
要等待promise里面的数组全都完成了之后,它会统一的来返回一个then,比如
promise.all([ $.ajax({url:'data/1.json',dataType:'json'}), $.ajax({url:'data/2.json',dataType:'json'}), $.ajax({url:'data/3.json',dataType:'json'}), ]).then((arr)=>{//因为有三个结果,所以返回的是一个数组,第一个function代表resovle,第二个function代表reject,这里也可以使用箭头函数,如果想要获取arr里面的数据,也可以直接将[data1,data2,data3]写到形参里。 let [data1,data2,data3] = arr; },(res)=>{ console.log('error'); })
这里就是用jquery中ajax的方法用异步的方式来进行模拟同步的方式,这里不存在顺序的问题,因为数据只有都完成了,然后把数据按照顺序一次全部返回,如果一个接口有问题,全失败。all的执行时间等于最慢的那个ajax,三个是并行在走的,promise.all()最大的缺点就是没有任何逻辑在里面,比如如果我们需要先执行a,b依赖于a的结果,这里就需要用到async和await了。
async/await
async/await已经取代了genrator,async/await是专门用来配合promise的,它模拟同步的方式来写异步的东西,这里不是一个普通的函数,这里是一个ansyc函数,这里面包含的是异步操作,如下,
aysnc funtion show(){//也可以写成箭头函数 let show = async() =>{}
let data1 = await $.ajax({url:'data/1.json',dataType:'json'});//准确的说await后面跟的是一个promise对象,但是jquery的ajax本身是包含promise的
let data2 = await $.ajax({url:'data/2.json',dataType:'json'});
let data3 = await $.ajax({url:'data/3.json',dataType:'json'});
console.log(data1,data2,data3);
}
show();
这里几乎是用同步的写法来写一个异步的操作了,注意点
1.尽管我们是在用一种同步的方式在写,但它背后依然是以异步的方式来执行,async只是为了你写的方便,它需要经过背后一套编译的东西,
2.这个async/await是这样的格式,
aysnc function(){}当然也可以是 let xxx = async()=>{}
它可以像正常函数一样写代码,但是如果里面有了promise操作,就需要加上一个await,等到这个函数结束了以后,代码就会往下执行,简单来说async这个函数是可以暂停的,这一点继承了生成器函数generator,async/await只是方便了模拟同步阅读操作的效率,而不会变成真正的同步的操作,它背后的性能依旧是回调的那些方式,非常的高,
加入逻辑操作,如果第一个失败了,第二个成功了的操作方式,示例
let show = async() =>{ let data1 = await $.ajax({url:'data/1.json',dataType:'json'}); if(data1.a<10){ let data2 = await $.ajax({url:'data/2.json',dataType:'json'}); console.log('a<10'); }else{ let data3 = await $.ajax({url:'data/3.json',dataType:'json'}); console.log('a>10'); } } show();
1.json里面是一个对象{'a':12};
如果某些成功某些失败也可以使用try/catch
promise几乎不能独立存在,它单独使用非常的难用,让promise大放异彩的就是async/await,它有一个专门的说法叫语法糖,它是让你用类似同步的方式写代码,但是当浏览器真正执行这个代码的时候,它会把这些函数编译回原来的那种嵌套回调写法,
2.Ajax同源策略
1.什么事同源策略,
浏览器的一种安全机制,源指,协议,域名,端口号,当我们脚本在运行时,浏览器会检测,它运行的脚本和取得数据与我们的html页面所在的源是否相同,相当于协议,域名,端口号是否和浏览器html的协议,域名,端口号是否一致。如果相同则是同源请求,如果不同就是跨域请求。默认情况下,浏览器不支持跨域请求。
2.解决跨域问题
1.JSONP
//这个方法不受同源策略的限制。也可以用js生成方法名,比较灵活 function getData(da1){ console.log(da1); } var script = document.createElement("script"); script.id = "JSONP"; script.src = "../js/JSONP.js"; document.body.appendChild(script);
JSONP.js的代码
getData({"name":"john","age":18});
//012ajax.html使用的
运用百度取词练习
function getData(data){ var script = document.querySelector("#JSONP");//选择刚创建的jsonp script.parentNode.removeChild(script);//因为input的keyup事件,所以每次输入都清除掉上一次的结果 $("ul").html("");//同时也清楚掉ul里面的结果。 for(var i = 0;i < data.g.length;i++){//因为返回的是对象,遍历对象 for(var index in data.g[i]){//用for in 方法遍历对象 var p1 = data.g[i][index]; //将对象的值写入p1 var p2 = index;} $("<li>"+ p1 + "--" + p2 +"</li>").appendTo("ul"); } } function getList(wd){ var script = document.createElement("script");//创建一个script script.id = "JSONP";//id script.src = "https://www.baidu.com/sugrec?&prod=pc&cb=getData&wd=" + wd; document.body.appendChild(script);//将jsonp文件放入树中; } $("input").keyup(function(){ var wd = $(this).val(); getList(wd); });
2.CORS
跨域资源共享是一般浏览器都支持的功能(ie10以上),由浏览器自动完成,cors的ajax和普通的ajax实现是一样的,cors关键在服务器端支持了跨域通信就行,普通ajax直接发出cors请求,在头信息中包含origin的字段,origin源是由浏览器自动追加的,指本次请求来自哪个源,服务器就根据这个值是否同意执行寻求,浏览器加了origin源之后,如果服务器发现origin不再它的许可范围内,就返回一个正常的http的响应,浏览器就发现这个回应的头里面没有包含跨域请求允许的信息,就知道出错,然后抛出一个异常,否则,浏览器允许跨域,返回对应的状态以及状态码200,
$.get("http://localhost/cors/cors.php",function(data){
console.log(data);
})
cors.php代码
<?php $person = array('name'=>'josh','age'=>18); header("Access-Control-Allow-Origin:*"); //在头信息上写入一个origin,要不然浏览器不能接受到跨域请求,则报错,可以写上指定的域名,或者写上* echo json_encode($person); ?>

浙公网安备 33010602011771号