Ajax-网页异步更新
(注:本章讲解涉及部分后端知识,将以php提供数据的方式进行相应的demo实现)
1:ajax的概念
全称:Asynchronous Javascript And Xml
AJAX不是一种新的编程语言,而是一种用于创建更快更好以及交互性更强的WEB应用程序技术,该技术在98年前后得到了应用。通过AJAX,你的JS可以通过JS的XMLHttpRequest对象在页面不重载的情况下与服务器直接进行通信。这样可以在服务器请求到想要的数据,而不是整个页面。AJAX的核心就是JS的XMLHttpRequest对象。xhr对象是在IE5中首次引入,它是一种支持异步请求的对象。
2:ajax的优势
- 无刷新更新数据。
- 异步与服务器通信。
- 基于标准被广泛支持。
- 前端与后端分离。
- 节省带宽。
3:编写步骤
1.创建XMLHttpRequest对象。
所有现代浏览器(IE7+,chrome,firefox,opera,safari)均内建XMLHttpRequest对象。但是IE5、6使用ActiveXObject对象。
function getAjax() { var xmlhttp = null; if(window.ActiveXObject){ //针对IE xmlhttp = new ActiveXObject(’Microsoft.XMLHTTP’); } else if(window.XMLHttpRequest){ xmlhttp = new XMLHttpRequest(); } return xmlhttp; }
2.打开与Server的连接,指定发送方式、URL以及权限等。
open方法:创建新的HTTP请求,并指定此请求的方法,URL以及验证信息。
xhr.open(type, url, async, user, password);
type:HTTP请求方式,GET、POST等。大小写不敏感。
url:请求地址。(get请求如果有传值直接以url?param=value的方式传递。post的方式直接在发送指令的时候传递)
async:布尔型,请求是否为异步方式。默认为true。如果为真,当状态改变时会调用onreadystatechange属性指定的回调函数。(可选)
注释:当您使用 async=false 时,请不要编写 onreadystatechange 函数 - 把代码放到 send() 语句后面即可:
xmlhttp.open("GET","test.txt",false); xmlhttp.send(); document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
user:如果服务器需要验证,此处指定用户名,如果未指定,当服务器需要验证时,会弹出验证窗口。(少用仅了解)
password:验证信息中的密码部分,如果用户名为空,则此值将会被忽略。(少用仅了解)
注:在AJAX中,其实我们就是来模拟正常的表单提交数据。正常的表单在POST数据时,会发送Content-Type字段,所以我们在AJAX中就要指定该字段值为application/x-www-form-urlencoded。并且对字段名称和值进行编码处理在发送。使用setRequestHeader:单独指定请求的某个HTTP头。
注:一些特殊字符可能与代码中的字符冲突(如URL中分隔符&等等),故数据应使用encocdeURIComponent()函数进行编码。
3.发送指令。
send():发送请求到HTTP服务器并接收回应。
此方法的同步或异步方式取决于open方法中的async参数,如果async为true,此方法将立即返回,如果为false,此方法将会等待请求完成或者超时时才会返回。
xhr.send(body);
body:通过此请求发送的数据。GET请求设置为null即可。
post和get方式实现ajax的不同之处
xmlhttp.open("GET","demo_get2.asp?fname=Bill&lname=Gates",true); xmlhttp.send(); xmlhttp.open("POST","ajax_test.asp",true); xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded"); xmlhttp.send("fname=Bill&lname=Gates"); //传参方式的不同以及编码方式的不同post提交需要被别,则需要指定编码方式与get的方式一样
4.等待并接收服务器返回的处理结果。
5.客户端接收。
6.释放XMLHttpRequest对象。
4:回调函数
通过onreadystatechange属性指定readystate属性改变时的事件处理回调函数。
xhr.onreadystatechange = function(){}
readyState属性:返回请求的当前状态。
- 0:对象已建立,尚未初始化(未调用open方法)。
- 1:对象已建立,尚未调用send方法。
- 2:send方法已调用。但是当前的状态以及HTTP状态未知。
- 3:开始接收数据,因为响应以及HTTP头不全,这时通过responseBody和responseText获取部分数据会出现错误。
- 4:数据接收完毕,此时可以通过responseBody和responseText获取完整的响应数据。
status属性:返回当前请求的状态码。
- 200 OK:请求文档已经找到,并正确返回。
- 304 Not Modified:拥有一个本地的缓存副本,服务器端内容与此相同。
- 403 Forbidden:请求者对所请求的文档不具有相应的权限。
- 404 Not Found:请求的文档没找到。
statusText属性:返回当前请求的响应行信息。
responseXML属性:将响应信息格式化为XML Document对象返回。
responseText属性:将响应信息作为字符串返回。
5:JS解析JSON
JSON:Javascript Object Notation,一种轻量级的基于文本的数据交换格式,易于人阅读和编写,也能提高网络传输速率。
ES5新增的两个方法:
JSON.parse:将JSON字符串数据转换为JSON对象。
JSON.stringify:将JSON对象转换为JSON字符串。
注:1、浏览器支持:IE8+。
2、JSON格式的字符串里面的key或者字符串型的value都必须用双引号包裹
6:局部数据刷新
demo讲解上述提到的知识点:操作相应的DOM节点(例如评论列表的分页效果)
html页面
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>新闻列表</title> <style type="text/css"> *{ margin:0; padding:0; } .box{ width: 80%; margin: 0 auto; } .newsTitle{ font-size: 24px; text-align: center; margin: 0 auto; padding: 20px 10px; font-weight: normal; letter-spacing: 10px; } .newsList{ display: block; margin: 0 auto; line-height: 50px; font-size: 16px; list-style: none; } .newsList li{ border-top: 1px dashed #f4f4f4; padding: 0 20px; } .newsList li:nth-child(odd){ background: #f3f3f3; } .newsPage{ display: block; margin: 0 auto; text-align: center; } .newsPage li{ margin:20px 5px; display: inline-block; padding: 5px 10px; border:1px solid #f3f3f3; font-size: 14px; } </style> </head> <body> <div class="box"> <h3 class="newsTitle">新闻列表</h3> <ul id="newsList" class="newsList"> <li>东航首位外籍女机长:来中国是最好的选择</li> <li>东航首位外籍女机长:来中国是最好的选择</li> <li>东航首位外籍女机长:来中国是最好的选择</li> <li>东航首位外籍女机长:来中国是最好的选择</li> <li>东航首位外籍女机长:来中国是最好的选择</li> </ul> <ul id="newsPage" class="newsPage"> <li data-page="1">1</li> <li data-page="2">2</li> <li data-page="3">3</li> <li data-page="4">4</li> <li data-page="5">5</li> <li data-page="6">6</li> <li data-page="7">7</li> <li data-page="8">8</li> <li data-page="9">9</li> <li data-page="10">10</li> </ul> </div> </body> <script type="text/javascript" src="ajax.js"></script> </html>
js页面
var oNewsPage=document.getElementById('newsPage'); var oNewsPage=Array.from(oNewsPage.children); var oNewsList=document.getElementById('newsList'); oNewsPage.forEach(function (value) { value.onclick=function () { oNewsList.innerHTML = ""; //获取页码值 var pageNum = value.getAttribute("data-page"); /*步骤一:创建XMLHttpRequest对象*/ var xhr = new XMLHttpRequest(); /*步骤二:请求配置*/ var pageNum = "pageNum="+ pageNum; //xhr.open('get','ajax.php?'+pageNum,true); xhr.open('post','ajax.php',true); /*步骤四:接受返回结果*/ xhr.onreadystatechange=function () { //根据状态返回码判定请求的状态 if (xhr.readyState === 4 && xhr.status === 200) { //获取返回结果 var newsList = JSON.parse(xhr.responseText)//返回结果通过json将字符串进行转换 //数据结果渲染到页面 newsList.forEach( v => { var oLi = document.createElement('li'); oLi.innerHTML = v.title; oNewsList.appendChild(oLi); }); } } /*步骤三:发送请求*/ //post请求需要设置编码格式 否则无法解析数据 xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); xhr.send(pageNum);//post方式将参数传递的方式 } })
php后台页面
<?php $pageNum=$_POST['pageNum']; //接收参数页码 //通过页码判断加载的内容 if ($pageNum == 1) { //通过二维数组存储数据 $arr = [ [ 'id' => 1, 'title' => '东航首位外籍女机长:来中国是最好的选择' ], [ 'id' => 2, 'title' => '南航首位外籍女机长:来中国是最好的选择' ], [ 'id' => 3, 'title' => '国际航空首位外籍女机长:来中国是最好的选择' ] ]; } else if ($pageNum == 2) { $arr=[ [ 'id' =>4, 'title'=>'世界那么大不如出去走走' ], [ 'id'=>5, 'title'=>'今天阳光明媚适合出去走走' ] ]; } else{ $arr=[ [ 'id' =>6, 'title'=>'我是第三页以后的内容' ], [ 'id'=>7, 'title'=>'我是第三页以后的内容' ] ]; } echo json_encode($arr); ?>
7:前后端分离(ajax函数的封装)
后台只管数据输出和业务逻辑处理,前端负责交互逻辑和界面展示。简单的说:前端静态页面中没有有后台程序代码,后台输出不带有HTML标签的数据。前后端分离靠ajax来实现数据的交互。
demo通过封装的ajax实现加载更多的功能以及通过事件源对象删除单条数据(本来打算将源码托管到GitHub,账号丢失)
*文件夹目录
1.html页面
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>新闻列表</title> <link rel="stylesheet" href="styles/ajax.css"> </head> <body> <div class="box"> <h3 class="newsTitle">新闻列表</h3> <ul id="newsList" class="newsList"> <li> 冬天来了,春天还会远么 <a class="deleteBtn" href="#">×</a> </li> <li> 面朝大海,幸福花开 <a class="deleteBtn" href="#">×</a> </li> <li> Nothing is impossible! <a class="deleteBtn" href="#">×</a> </li> <li> 水能载舟亦能覆舟 <a class="deleteBtn" href="#">×</a> </li> <li> 中国是最好的选择 <a class="deleteBtn" href="#">×</a> </li> </ul> <div id="loadMoreInfo" class="loadMoreInfo"> <img id="loadingImg" class="loading" src="images/timg.gif" /> 加载更多... </div> </div> </body> <script type="text/javascript" src="scripts/common.js"></script> <script type="text/javascript" src="scripts/ajax.js"></script> </html>
2.css文件
@charset "utf-8"; /* CSS Document */ *{ margin:0; padding:0; } body{ background: #7CCD7C; } .box{ width: 80%; margin: 0 auto; } .newsTitle{ font-size: 24px; text-align: center; margin: 0 auto; padding: 20px 10px; font-weight: normal; letter-spacing: 10px; } .newsList{ display: block; margin: 0 auto; line-height: 50px; font-size: 16px; list-style: none; } .newsList li{ padding: 0 20px; box-shadow: 0 0 10px #eeeeee; } .box .newsList li:hover{ background: #B0E2FF; } .newsList li:nth-child(odd){ background: #f3f3f3; } .newsList li:nth-child(even){ background: #eeeeee; } .deleteBtn{ float: right; text-decoration: none; font-size: 16px; color: #555555; } .loadMoreInfo{ margin-top: 10px; text-align: center; line-height: 50px; font-size: 16px; background: #ffffff; cursor: pointer; vertical-align: middle; margin-bottom: 20px; } .loadMoreInfo img{ display: none; width: 20px; height: 20px; vertical-align: middle; }
3.公共js(封装的$函数以及ajax函数)
/* 封装$函数 参数说明: id:标签的id属性值 */ function $(id) { return document.getElementById(id); } /* 封装ajax函数 参数说明:对象作为参数不用考虑参数顺序问题 type:请求类型; url:请求访问地址; param:请求数据,支持对象也支持字符串; asyn:是否异步加载,boolean类型,true异步,false同步 beforesend:回调函数在发送请求之前执行 success:回调函数,请求成功时执行 complete:回调函数,请求完成后执行 */ function ajax({type,url,param,asyn=true,beforesend,success,complete}) { //创建XMLHttpRequest对象 var xhr = new XMLHttpRequest(); //param参数为对象时进行拼接字符串 if (param && typeof(param) === 'object') { var str; for(var child in param){ //encodeURIComponent编码参数,避免特殊字符分割时丢失 str+=encodeURIComponent(child) + '=' + encodeURIComponent(param[child]) + '&' } param=str.slice(0,-1);//截取拼接完成后最后的&符 } //get请求对url传参进行拼接 if (type.toUpperCase()==="GET" && param) { url+='?'+param; } //请求配置 xhr.open(type , url, asyn); //获取返回的数据 xhr.onreadystatechange = function () { if (xhr.readyState === 4 && xhr.status === 200) { //获取返回的数据并转换 success(xhr.responseText); } //请求完成后的函数 complete && complete(); } //发送请求 beforesend && beforesend(); if (type.toUpperCase()==="POST") { //post请求设置编码方式 xhr.setRequestHeader("Content-Type",'application/x-www-form-urlencoded') //post请求时通过send向body传参(无论param参数是否为空,必须传) xhr.send(param); } else{ //get请求发送请求 xhr.send(); } }
4.页面js
var oLoadMoreInfo = $("loadMoreInfo"); var oNewsList = $("newsList"); var oLoadingImg = $("loadingImg"); oLoadMoreInfo.onclick=function () { ajax({ type:'post', url:'php/ajax.php', beforesend:function () { //发送前显示加载过程中的动态效果 oLoadingImg.style.display="inline-block" }, success:function (data) { //接受返回的数据进行转换并渲染到页面 var data=JSON.parse(data); data.forEach(function (value) { var li=document.createElement("li"); li.innerHTML=value+'<a class="deleteBtn" href="#">×</a>'; oNewsList.appendChild(li); }) }, //完成后显示渲染出来的网页效果,关闭等待效果 complete:function () { oLoadingImg.style.display="none" } }) } newsList.onclick=function (ev) { var e=ev||window.event; //获取事件原对象 var tar=e.target||e.srcElement; //判断事件原对象是否为a标签nodenName的值都是大写 if (tar.nodeName==="A") { oNewsList.removeChild(tar.parentNode); } }
5.php后台
<?php sleep(2);//本地测试资源加载速度过快无法看出加载的动态效果 $news=[ '东航首位外籍女机长:来中国是最好的选择', '南航首位外籍女机长:来中国是最好的选择', '国际航空首位外籍女机长:来中国是最好的选择', '东航首位外籍女机长:来中国是最好的选择', '南航首位外籍女机长:来中国是最好的选择', '国际航空首位外籍女机长:来中国是最好的选择', '东航首位外籍女机长:来中国是最好的选择', '南航首位外籍女机长:来中国是最好的选择', '国际航空首位外籍女机长:来中国是最好的选择', '东航首位外籍女机长:来中国是最好的选择', '南航首位外籍女机长:来中国是最好的选择', '国际航空首位外籍女机长:来中国是最好的选择' ]; echo json_encode($news, JSON_UNESCAPED_UNICODE); /* PHP的json_encode来处理中文的时候, 中文都会被编码, 变成不可读的, 类似”\u***”的格式,PHP5.4,JSON_UNESCAPED_UNICODE:Json不要编码Unicode*/
6.图片资源
8:ajax的依赖调用
在使用ajax异步调用的时候,可能碰到同时调用多个ajax的情况,而且多个ajax之间还存在依赖关系。
引用回调函数的嵌套说明ajax的以来调用:
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>回调函数的嵌套</title> </head> <body> </body> <script type="text/javascript"> function a(d, e) { d && d(e); } function b(f) { console.log('函数b!'); f && f(); } a(b, function() { console.log('实参e(回调函数)'); }); /*回调函数的简单理解:函数在方法中以参数的方式进行传递*/ /*这里提供两种形式理解回调函数的嵌套*/ /* function a(d, e) { d && d(e); } a( function b(f){ console.log('函数b!'); f && f(); }, function() { console.log('实参e(回调函数)'); } );*/ </script> </html>
demo:逐个异步验证验证码、用户名和密码,只有用户通过,才能异步验证密码。
此处只给出部分重要代码逐个调用封装的ajax方法(前后端分离的demo封装的ajax方法)进行异步验证验证码、用户名和密码:
// 表单提交事件用纯ajax实现表单验证 // 验证验证码 var sCaptcha = oCaptcha.value; ajax({ type: 'POST', url: 'login.php', data: {captcha: sCaptcha}, success: function (data) { if(data == 1) { // 验证账号 var sAccount = oAccount.value; ajax({ type: 'POST', url: 'login.php', data: {account: sAccount}, success: function (data) { if(data == 1) { // 验证密码 var sPassword = oPassword.value; ajax({ type: 'POST', url: 'login.php', data: {password: sPassword}, success: function (data) { if(data == 1) { oShow.innerHTML = '登录成功!'; } else { oShow.innerHTML = '密码错误!'; } } }); } else { oShow.innerHTML = '账号错误!'; } } }); } else { oShow.innerHTML = '验证码错误!'; } } });
9:Promise介绍
Promise函数,是一个构造函数,它实际上是对回调函数的一种封装 对异步编程的一种改进。
1>Promise对象的特点:
1.Promise对象代表一个异步操作,有三种状态:Pending(进行中)、Resolved(已完成,又称Fulfilled)和Rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。
2.一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从Pending变为Resolved和从Pending变为Rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。就算改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。
Promise的优点:
Promise对象可以将异步操作以同步操作的流程表达出来,避免层层嵌套的回调函数。此外,Promise对象提供统一的接口,使得控制异步操作更加容易。
Promise的缺点:
1.无法取消Promise,一旦新建它就会立即执行,无法中途取消。
2.如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。
3.当处于Pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。
2>Promise的基本用法
Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。它们是两个函数,由JavaScript引擎提供,不用自己部署。(Promise新建后就会立即执行。)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Promise</title> </head> <body> <script> // 创建promise对象(创建后就被执行) var oP = new Promise(function (resolve, reject) { console.log('立即执行'); resolve(); reject(); }); </script> </body> </html>
resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”(即从Pending变为Resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;
reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从Pending变为Rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
1)Promise的then方法:指定Resolved状态和Reject状态的回调函数。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Promise</title> </head> <body> <script> // 创建promise对象 var oP = new Promise(function (resolve, reject) { console.log('立即执行'); // resolve(); /*状态由pending 变为执行成功, 调用then函数的第一个回调函数*/ reject(); /*想要查看reject对应的then的回调函数, 可将resolve()函数注释*/ /*reject函数单独执行异常,将then的第二 个参数回调函数注释可查看*/ }); oP.then(function() { console.log('第一个'); //只执行第一个then回调函数(一旦执行状态就无法改变) }, function () { console.log('第二个'); }); </script> </body> </html>
then方法可以接受两个回调函数作为参数。
第一个回调函数:Promise对象的状态变为Resolved时调用
第二个回调函数:Promise对象的状态变为Reject时调用。其中,第二个函数是可选的,不一定要提供。这两个函数都接受Promise对象传出的值作为参数。
then方法支持链式写法且同时调用
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Promise</title> </head> <body> <script> // 创建promise对象 var oP = new Promise(function (resolve, reject) { console.log('立即执行'); resolve(); reject(); }); // 链式写法 oP.then(function() { console.log('第一个'); }, function () { console.log('第二个'); }).then(function() { console.log('第三个'); }).then(function () { console.log('第四个'); }); </script> </body> </html>
只有被Promise封装过了,回调才能保证顺序。 也就是Promise(意为承诺)设计的初衷。但前一个方法必须在它最后执行resolve(),后一个方法才可以开始。 如果执行了reject(),则进入catch()方法。这里不能单纯的理解为 resolve就是success,reject就是error 现就职于阿里的大名鼎鼎的阮一峰老师,喜欢管它叫状态机,这是非常恰当的叫法。
2)catch方法:catch方法是.then(null, rejection)的别名,用于指定发生错误时的回调函数。Promise对象的错误具有“冒泡”性质,会一直向后传递,直到被捕获为止。也就是说,错误总是会被下一个catch语句捕获。一般来说,不要在then方法里面定义Reject状态的回调函数(即then的第二个参数),总是使用catch方法。如果没有使用catch方法指定错误处理的回调函数,Promise对象抛出的错误不会传递到外层代码,即不会有任何反应。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Promise</title> </head> <body> <script> // 创建promise对象 var oP = new Promise(function (resolve, reject) { console.log('立即执行'); // resolve(); reject(); }); // 链式写法 oP.then(function() { console.log('第一个'); }, function () { console.log('第二个'); }) // catch捕获错误 oP.catch(function () { console.log('出错啦!'); }); // console.dir(oP); </script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Promise</title> </head> <body> <script> // 创建promise对象 var oP = function(){ return new Promise(function (resolve, reject) { //报错x未定义,无输出(为捕获异常) resolve(x+2); })}; oP().then(function() { console.log('执行正确'); }) </script> </body> </html>
3>promise构造函数身上的方法
1)Promise.all():Promise.all方法用于将多个Promise实例,包装成一个新的Promise实例。
var p = Promise.all([p1,p2,p3]);
promise.all方法接受一个数组作为参数,p1、p2、p3都是Promise对象的实例。
p的状态由p1、p2、p3决定,分成两种情况。
(1)只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。
(2)只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Promise</title> </head> <body> <script> var p1 = new Promise(function (resolve, reject) { console.log('p1'); resolve(); }); var p2 = new Promise(function (resolve, reject) { console.log('p2'); reject(); }); var p3 = new Promise(function (resolve, reject) { console.log('p3'); resolve(); }); var p4 = Promise.all([p1, p2, p3]); console.log(p4);//返回值reject </script> </body> </html>
2)Promise.race():将多个Promise实例,包装成一个新的Promise实例。
var p = Promise.race([p1,p2,p3]);
上面代码中,只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p的回调函数
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Promise</title> </head> <body> <script> var p1 = new Promise(function (resolve, reject) { setTimeout(function () { console.log('p1'); resolve(); }, 400); }); var p2 = new Promise(function (resolve, reject) { setTimeout(function () { console.log('p2'); reject(); }, 800); }); var p3 = new Promise(function (resolve, reject) { setTimeout(function () { console.log('p3'); resolve(); }, 2000); }); var p4 = Promise.race([p1, p2, p3]); /*p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。 率先改变的 Promise 实例的返回值,就传递给p的回调函数。*/ console.log(p4);//返回值reject </script> </body> </html>
4>promise改造ajax依赖调用
待补充
10:ajax的同源策略
同源策略(same origin policy)是一种约定,是由netscape公司引入浏览器的,他是浏览器最核心最基本的安全功能。现在所有支持JS的浏览器都会使用这个策略。
所谓同源:是指协议、域名、端口都相同。
目的:保证用户信息的安全,防止恶意的网站窃取数据。
限制范围:
1:cookie,localStorage和IndexDB无法读取。
2:DOM无法获得。
3:AJAX请求不能发送。
11:jsonp跨域
JSONP = JSON WITH PADDING。一种数据调用的方式。
AJAX无论请求什么页面,因为同源策略的限制,只要是跨域就一律不准。不过我们发现凡是拥有src这个属性的标签都拥有跨域的能力,如img,iframe,script。那我们就可以把数据装载到JS文件内,供客户端调用和进一步处理。
步骤:
1:定义一个回调函数。
2:创建script标签,指定src地址,并添加到页面中。
注:src必须跟着一个参数callback来指定回调函数名称。
jsonp跨域demo
待补充。。。。。。
12:服务器端跨域
CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。
CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。
浏览器发起CORS请求,都会在请求头信息中增加一个Origin字段。该字段用来说明本次请求来自哪个源(协议 + 域名 + 端口)。服务器根据这个值,来决定是否同意这次请求。
实现方式:
在服务器端指定Access-Control-Allow-Origin头信息,该字段是必须的。它的值要么是请求时Origin字段的值,要么是一个*,表示接受任意域名的请求。如果Origin指定的值不在许可范围内,服务器返回一个正常的HTTP响应。浏览器如果发现响应头信息中没有包含Access-Control-Allow-Origin字段就知道出错了,从而抛出一个错误,被XMLHttpRequest的onerror回调函数捕获。
待补充。。。。。。
13:get和post提交
1:功能
get多用于从服务器上获取数据,post多用于向服务器发送数据。
2:数据提交
GET请求的数据会附在URL之后(就是把数据放置在HTTP协议头中),以?分割URL和传输数据,参数之间以&相连。POST把提交的数据则放置在是HTTP包的包体中。
3:数据大小
GET请求传送的数据量比较小,达能大于2KB,这个受浏览器的限制。而POST请求传送的数据量比较大,一般默认为不受限制。其实大小受服务器的限制。
4:安全性
GET安全性非常低,POST的安全性较高。