1、javascript的同源策略
一个脚本只能读取来自同一来源的窗口和文档的属性,这里的同一来源指的是主机名、协议、端口号的组合
协议:http ftp https
主机名:localhost 127.0.0.1
端口号:80
http协议默认端口号:80
https协议默认端口号:8083
同源策略是用来保护我们的文件不被外来的域名随便串改
同源策略带来的麻烦:ajax在不同的域名下的请求无法实现
如果说想要请求其它来源的js文件,或者json数据,可以通过josnp来解决
JSONP的实现原理:通过动态创建script表 function jsonpCallback(result){ console.log(var i in result){ console.log(result[i]) } } var JSONP=document.createElement('script'); JSONP.type="text/javascript" JSONP.src="http://xxxxx.com/servies.php?callback=jsonpCallback" document.body.appendChild(JSONP); //php //服务端返回json数据 $arr=array('a'=>1,'b'=>2,'c'=>3); $result=json_encode($arr); //动态执行回调函数 $callback=$_GET('callback'); echo $callback."($result)";
、ajax 的基本概念
了解这个概念,同步交互与异步交互
同步交互:客户端浏览器给服务器发送一个请求,服务器返回一个页面,返回的页面会吧之前的界面给覆盖,我们把这种交互称为同步交互.
异步交互:
异步交互就是客户端浏览器给服务器发送一个请求,服务器返回数据,返回的数据不会吧之前的界面覆盖,我们把这种交互称为异步交互。
Ajax 主要的应用场景,页面不刷新,就可以与服务端进行动态的数据交互。
2、交互的原理
我们在浏览器怎么给服务器发送请求,点击超链接,提交表单,浏览器地址输入地址,都是给服务器发送请求。实际上都是浏览器帮我去发送请求.
3、ajax 跨域
这个跨域. 我们要知道什么是跨域,跨域之后我们怎么去做处理
跨域:假设我访问a 站点,在a站点得到一个页面,在a 站点的这个页面想去访问b 站点的资源,这个是就会产生一个跨域的效果,跨域浏览器是有安全限制的
jsonp (xmlhttpRequest去创建一个script标签),然后通过script去发送请求,服务器返回了数据,返回的数据浏览器会直接以javascript的方式去解析服务端返回的数据
$('.btn').on('click',function(){ var phone=$('#phone').value() $.ajax({ type:'get', url:"https://api.jisuapi.com/shouji/query", data:"appkey=7ca5f245245f2b88&shouji="+phone, dataType:"jsonp",//开启跨域 success:function(result){ console.log(result) } }) })
jsonp底层: 只支持get,不支持post
//定义成一个全局的函数 function getInfo(obj){ console.log(obj); } document.querySelector("input").onclick=function(){ //点击这个按钮,我给jd 发送请求. //http://www.jd.com/jd.php //假设我使用XMLHttpRequest 很明显就跨域了 var script=document.createElement("script"); //这个请求暂时是没有发送出去. //把这个标签挂载到页面上面才能够发送请求callback 跨域的通用的参数名称. script.src="http://www.jd.com/jd.php?callback=getInfo"; //因为现在服务端给我返回的数据{"username":"zhangsan","age":11} //客户端以js 的方式去解析这个数据{"username":"zhangsan","age":11} //不符合js 的语法,所以就报错了. document.body.appendChild(script); //客户端浏览器得到是这样的数据getInfo({username: "zhangsan", age: 11}) //以js 的方式去解析,就会去调用getInfo 的函数. //我现在的目的是想在页面里面得到这个服务端返回的数据 //1:客户端给服务端传递一个回调函数 ,它还需要定义一个函数 //2:服务端返回的是一个回调函数的调用,并且将服务端的数据包在这个函数的调用里面. //现在我只能解决get 方式的跨域,我们把这个种跨域叫做jsonp //把数据作为参数传递过来 //为什么只能解决get 方式的跨域,底层使用script 标签发送请求 //src href 这些发送的请求都是get 请求. //jsonp ,客户端给服务端传递一个回调函数,服务端返回的是一个回调函数的调用,并且将数据放在回调函数里面作为参数传递过来. }
现在采用的跨域方案是jsonp jsonp 只支持get 方式的跨域,并不支持post,
如果我要给跨域的服务器传递非常多数据,get 对请求的数据的大小有限制,传不过去.
我们就要处理post 方式的跨域
使用一个叫做cors 的方案 跨域资源共享. 其实这个是需要在服务器端进行一个配置,其实就服务端给客户端一个响应头,就搞定.
jquery只支持jsonp,不支持cors
cors
实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。
服务器设置请求头:Access-Control-Allow-Origin启用CORS。
参考:https://www.cnblogs.com/itmacy/p/6958181.html
cors详细解释:https://www.cnblogs.com/loveis715/p/4592246.html
4、ajax用在哪些地方
360 的案例
输入关键字,输入关键字,触发一个事件,执行一个方法,调用JavaScript的这个api 。
通过XMLHttpRequest 给服务器发送请求,通过XMLHttpRequest 接收数据.
然后接收到数据之后,通过dom 把这个数据写到页面上面,通过这样的过程来完成异步交互的操作.
Ajax,检测用户名是否存在,失去焦点发送请求
Ajax 也可以用来做性能优化,比如我一个页面非常庞大,这个页面不可能一次加载完毕.
实现一个滚动加载
5、原生ajax
Ajax 是什么? (用来实现客户端与服务器端的异步通信效果,实现页面的局部刷新)
如何创建一个Ajax?
/* 第一步:创建ajax对象 var xhr = new XMLHttpRequest(); //var xhr = new ActiveXObject('Microsoft.XMLHTTP'); ie6一下 第二步:请求准备 xhr.open( 'get' , 'firstAjax.txt' , true ); 参数1:请求方式 get/post 在form提交的时候: Get 把传输数据放在url后面 ,会有缓存,隐私会被暴露出来 (get.php?usermane=aa&age=33) post把数据放在头文件里面 用来往后端提交数据,不会有缓存;只有往后端获 取数据才会有缓存; 一般用post是提交数据,如果获取数据需要提交一些参数才能获取,而这些参数数据又不想暴露在地址栏,那就可以用post了 参数2:请求路径 参数3:是否异步 true 异步 请求的过程不会影响后面程序的执行 false 同步 当你后续代码要用到跟前面挂钩时,用同步 第三步:正式发送请求 xhr.send(); 第四步:监听请求状态 xhr.readyState :请求状态码 0 :请求还没发生(open执行之前) 1 :请求已经建立,还没发送(执行了open) 2 :请求已经发送,正在处理(执行了send) 3 :请求处理中,有一部分数据可以用,但还有没有完成的数据。 4 :请求完全完成 onreadystatechange :请求状态码发生改变的时候触发 xhr.responseText : 返回的数据 xhr.status : HTTP状态码 */ var xhr=null; if(window.XMLHttpRequest){ //判断是window底下的属性是否存在 xhr=new XMLHttpRequest(); }else{ xhr=new ActiveXObject('Microsoft.XMLHTTP'); } // var xhr = new XMLHttpRequest(); xhr.open( 'get' , 'test.php' , true ); xhr.send(); xhr.onreadystatechange = function(){ if ( xhr.readyState == 4 ) { if ( xhr.status >= 200 && xhr.status < 300 ) { console.log(xhr.responseText) }else { alert( '请求好像遇到了点问题,状态码:' + xhr.status ); }; } };
Post: xhr.open('post','1post.php',true); xhr.setRequestHeader('content-type','application/x-www-form-urlencoded'); //告诉后端发送数据的编码类型 xhr.send('username=leo&age=30');//post方式,数据放在send()里面作为参数传递 xhr.onreadystatechange=function(){ if(xhr.readyState==4){ if(xhr.status==200){ alert(xhr.responseText) }else{ alert('出错了,Err'+xhr.staus) } } }
2、Json:是一种轻量级的数据交换格式, 数据格式简单, 易于读写, 占用带宽小
JSON字符串转换为JSON对象: var obj =eval('('+ str +')'); var obj = str.parseJSON(); var obj = JSON.parse(str); JSON对象转换为JSON字符串: var last=obj.toJSONString(); var last=JSON.stringify(obj);
5、简述ajax 的过程。
1. 创建XMLHttpRequest对象,也就是创建一个异步调用对象 2. 创建一个新的HTTP请求,并指定该HTTP请求的方法、URL及验证信息 3. 设置响应HTTP请求状态变化的函数 4. 发送HTTP请求 5. 获取异步调用返回的数据 6. 使用JavaScript和DOM实现局部刷新
6、http状态码
1XX: 一般用来判断协议更换或者确认服务端收到请求这些 100: 服务端收到部分请求,若是没有拒绝的情况下可以继续传递后续内容 101: 客户端请求变换协议,服务端收到确认 2xx: 请求成功,是否创建链接,请求是否接受,是否有内容这些 200: (成功)服务器已成功处理了请求。 201: (已创建)请求成功并且服务器创建了新的资源。 202: (已接受)服务器已接受请求,但尚未处理。 204: (无内容)服务器成功处理了请求,但没有返回任何内容。 3XX: 一般用来判断重定向和缓存 301: 所有请求已经转移到新的 url(永久重定向),会被缓存 302: 临时重定向,不会被缓存 304: 本地资源暂未改动,优先使用本地的(根据If-Modified-Since or If-Match去比对服务器的资源,缓存) 4XX: 一般用来确认授权信息,请求是否出错,页面是否丢失 400: 请求出错 401: 未授权,不能读取某些资源 403: 阻止访问,一般也是权限问题 404: 页面丢失,资源没找到 408: 请求超时 415: 媒介类型不被支持,服务器不会接受请求。 5XX: 基本都是服务端的错误 500: 服务端错误 502: 网关错误 504: 网关超时
4、页面编码和被请求的资源编码如果不一致如何处理?
对于ajax请求传递的参数,如果是get请求方式,参数如果传递中文,在有些浏览器会乱码,不同的浏览器对参数编码的处理方式不同,所以对于get请求的参数需要使用 encodeURIComponent函数对参数进行编码处理,后台开发语言都有相应的解码api。对于post请求不需要进行编码
➤存储问题:
➤异步:
//循环运行期间,JS执行和DOM渲染暂时卡顿 var i,sum=0; for( i=0;i<1000000;i++){ sum++ } console.log(sum) //单线程,同一时间只能做一件事 //alert不处理,js执行和DOM渲染暂时卡顿 console.log(100); alert('hello world'); console.log(200) //解决方案:异步 console.log(100); setTimeout(function(){ console.log(200) //1000s之后执行 },1000) //先不管它,先让其它js代码运行 console.log(300) console.log(400) //ajax console.log(100) $.ajax({ url:'xxx', success:function(result){ //ajax加载完才执行 console.log(result) //先不管它,先让其它js代码运行 } }) console.log(300) console.log(400)
/*先走主进程,再看异步队列有没有异步函数,发现只有 function(){ console.log(1) }, 暂时还没有第一个定时器的,因为要等100ms才放入异步队列,所以先把第二个定时器拿到主进程中执行,再去异步队列看有没有异步函数,一直监视*/ $.ajax({ url:'xxxx', success:function(reslut){ //等ajax加载完成时放入异步队列,有可能在定时器前面或者后面,或者在第一个定时器前 console.log('a') } }) setTimeout(function(){ console.log(100) //200ms 才放入异步队列,执行的是function(){ console.log(100) } },200) setTimeout(function(){ console.log(1) //立即放入异步队列 function(){ console.log(1) } }) console.log(200) //主进程
//jquery1.5之前,现在也这么写 var ajax=$.ajax({ url:'data.json', success:function(){ console.log('success1') console.log('success2') console.log('success3') }, error:function(){ console.log('error') } }) console.log(ajax) //返回一个XHR对象 //1.5之后 var ajax=$.ajax('data.json') ajax.done(function(){ console.log('success1') }).fail(function(){ console.log('error') }).done(function(){ console.log('success2') }) console.log(ajax) //返回一个deferred对象 //还可以这么写,很像promise的写法 var ajax=$.ajax('data.json') ajax.then(function(){ console.log('success1') }.function(){ console.log('error1') }) .then(function(){ console.log('success2') }.function(){ console.log('error2') }) /* 1.5的变化 无法改变JS异步和单线程的本质 只能从写法上杜绝callback这种形式 它是一种语法糖形式,但是解耦了代码 很好的体现:开放封闭原则 */
/* var wait=function(){ var task=function(){ console.log('执行完成') //dosomeing1 //dosomeing2 } setTimeout(task,2000) } wait() */ //怎么封装成Deferred function waitHandle(){ //定义 var dtd=$.Deferred() var wait=function(dtd){ var task=function(){ console.log('执行完成') //成功 dtd.resolve() //失败 //dtd.reject() } setTimeout(task,2000) //wait返回 return dtd } //最终返回 return wait(dtd) } var w=waitHandle() w.then(function(){ console.log('ok 1') },function(){ console.log('err 1') }) w.then(function(){ console.log('ok 2') },function(){ console.log('err 2') }) /* 总结,dtd的api可分为两类,用意不同 第一类:dtd.resolve dtd.rejet(主动要做的事) 第二类:dtd.then dtd.done dtd.fail (dtd.then 是被动监听 reslove或者reject ) 这两类应该分开,否则后果很严重 可以在上面代码最后执行dtd.reject()试下结果 */
//使用dtd.promise() //已封装好的A员工 function waitHandle(){ //定义 var dtd=$.Deferred() var wait=function(dtd){ var task=function(){ console.log('执行完成') //成功 dtd.resolve() //失败 //dtd.reject() } setTimeout(task,2000) //wait返回 return dtd.promise() //注意,这里返回的是promise 而不是直接返回deferred对象 } //最终返回 return wait(dtd) } //使用B员工 var w=waitHandle() //w接收的是一个promise对象 w.reject() $.when(w).then(function(){ console.log('ok 1') },function(){ console.log('err 1') })
➤性能优化:
1、 为什么利用多个域名来存储网站资源会更有效?
CDN缓存更方便
突破浏览器并发限制
节约cookie带宽
节约主域名的连接数,优化页面响应速度
防止不必要的安全问题
➤其它