12.第21章:Ajax与Comet

1.XMLHttpRequest对象


1.1 创建XMLHttpRequest对象

IE7及之前的版本:不支持new,要兼容IE7及之前版本,需要按照如下方法。



若不需要兼容IE7及之前版本

let xmr=new XMLHttpRequest();

1.2 调用open方法
接收三个参数:请求方式(get,post)、请求地址url、同步异步(默认异步,值为true,可以不提供最后一个参数,使用默认参数)

let xhr=new XMLHttpRequest();
xhr.open("GET",url,true);

1.3 调用send方法
接收一个参数:要发送的数据data,没有就是null

  • 发送get请求
let xhr=new XMLHttpRequest();
xhr.open("GET",url+"?name1=value&name2=value2",true);
 xhr.sent();
  • 发送post请求时,需要设置请求头部
let xhr=new XMLHttpRequest();
 xhr.open("POST","http://",true);
//设置发送数据格式
 xhr.contentType="application/x-ww-form-urlencoded";
 xhr.sent("name1=value&name2=value2");

HTTP头部信息:

1.4 添加onreadystatechange事件,为了跨浏览器的兼容性,将其放在open()方法之前。
readyState表示请求的状态,当请求的状态值发生变化时,会触发onreadystatechange()事件。

  • get请求全部代码
let xhr=new XMLHttpRequest();
xhr.onreadystatechange=function(){
//表示请求完成
if(xhr.readyState==4){
     //表示http状态码的取值
    if(xhr.status>=200&&xhr.status<300||xhr.status==304){
     let responceJson=JSON.parse(xhr.responseText);      
    }
    else{
      alert("request not sucess:"+xhr.status);
    }
}

xhr.open("GET",url+"?name1=value&name2=value2",true);
 xhr.sent();
  • post请求全部代码
let xhr=new XMLHttpRequest();
xhr.onreadystatechange=function(){
  if(xhr.readyState==4){
    if(xhr.status>=200&&xmr.status<300||xmr.status==304){
      let responceJson=JSON.parse(xhr.responseText);    
   }
     else{
      alert("request not sucess:"+xhr.status);
    }
  }
 xhr.open("POST","http://",true);
//设置发送数据格式
 xhr.contentType="application/x-ww-form-urlencoded";
 xhr.sent("name1=value&name2=value2");
}

HTTP状态码:
500:内部错误
404:找不到页面(page not found)
403:禁止访问(forbidden)
304:没有被修改
200:一切正常

  • 自己实现一个ajax
<script>
  function createAjax(url,method,data) {
      let xmlHttp=window.XMLHttpRequest?new XMLHttpRequest():
          new ActiveXObject('Microsoft.XMLHTTP');
      
      xmlHttp.onreadystatechange=function () {
          //readyState等于4表示发送完成
          if(xmlHttp.readyState===4){
              if((xmlHttp.status>=200&&xmlHttp.status<300)||xmlHttp.status===304){
                  //成功之后的处理
                  let responseJson=JSON.parse(xmlHttp.responseText);
              }
              else{
                  alert('请求失败'+xmlHttp.status);
              }
                  
          }
      };
      if(method==='POST')
      {
          xmlHttp.open(method,url,true);
          xmlHttp.setRequestHeader('content-type','application/x-www-form-urlencoded');
          xmlHttp.send(JSON.stringify(data));
          
      }
      else {
          url=url+'?data='+JSON.stringify(data);
          xmlHttp.open(method,url,true);
          xmlHttp.send();
      }
      
  }    
</script>

2 XMLHttpRequest 2级

2.1 FormData

之前使用post发送表单请求



使用FormData实现,不需要设置头部


3.跨域资源共享

默认情况下,XHR对象只能访问与包含它的页面位于同一个域中的资源。
CORS定义了在访问跨域资源时,浏览器与服务器应该如何沟通,基本思想是:使用自定义的Http头部让浏览器和服务器进行沟通,从而决定请求或响应应该成功或者失败。


3.1 IE对CORS的实现

微软在IE8中引入XDomainRequest类型,如下是XDR与XHR类型的不同之处:



涉及到的方法:
1)open()方法只接收两个参数:请求类型、url,所有XDR请求都是异步操作。
2)请求成功后会触发load事件,响应的数据会保存在responseText属性中。
3)请求错误会触发error事件。
4)请求返回前调用abort()方法可以终止请求。
5)XDR也支持timeout属性和ontimeout事件处理程序。
6)contentType属性,用来表示发送数据的格式。

let xdr=new XDomainRequest();
//请求成功
xdr.onload=function(){
    alert(xdr.responseText);
}
//请求失败
xdr.onerror=function(){
     alert(“请求失败”);
}
xdr.timout=1000;
xdr.ontimeout=function(){
    alert("请求超时");
}
xdr.open("post","http://");
//设置发送数据格式
xdr.contentType="application/x-ww-form-urlencoded";
xdr.sent("name1=value&name2=value2");

3.2 其他浏览器对CORS的实现

通过XMLHttpRequest对象实现了对CORS的原生支持。无需额外编写代码。

let xhr=new XMLHttpRequest();
xhr.onreadystatechange=function(){
if(xhr.readyState==4){
   if(xhr.status>=200&&xhr.status<300||xhr.status==304){
       alert(xhr.responseText);
     }
    else{
        alert("请求失败,状态码"+xhr.status);
    }
}
xhr.open("get","http://",true);
xhr.send(null);
}

对于本地资源,最好使用相对URL
访问远程资源,使用绝对URL。

3.3 跨浏览器的CORS
function createCORSRequest(method,url){
    var xhr=new XMLHttpRequest();
    //如果xhr里面有withCredentials属性,说明是非IE浏览器
    if("withCredentials" in xhr){
    xhr.open(method,url,true);
  }else if(typeOf XDomainRequest !="undefined"){
      xhr=new XDomainRequest();
      xhr.open(method,url);
   }else{
      xhr=null;
    }
return xhr;
}

let request=createCORSRequest("get","http:");
if(request){
request.onload=function(){
    alert(request.responseText);
}
request.onerror=function(){
   alert("请求失败");
}
request.send();
}

3.其他跨域技术

3.1 图像Ping

图像Ping是与服务器进行简单,单向的跨域通信的一种方式,请求的数据是通过查询字符串形式发送的,但响应可以是任意内容,通常是像素图或204响应。
图像Ping,浏览器得不到任何具体数据,但通过侦听load和error事件,它能知道响应是什么时候接收到的。


3.2 JSONP

JSONP由两部分组成:回调函数、数据
回调函数是当响应到来时应该在页面中调用的函数,数据就是传入回调函数的JSON数据。
JSONP通过动态<script>元素来使用的。

<script>
    /*jsonp*/
    function handleCallback(data){
        //这里就是想要 得到的信息
        console.log(data);

    }
    let script=document.createElement('script');
    script.src='http://coding.imooc.com/api/js?callback=handleCallback';
    document.body.insertBefore(script,document.body.firstChild);
</script>
  • 与图像ping相比优点:
    能够直接访问响应文本,支持浏览器与服务器的双向通信。
  • 缺点:
    JSONP是从其他域中加载代码执行,如果其他域不安全,只能放弃调用。
    无法确定JSONP请求是否失败。
3.3 Comet

Ajax是从页面向服务器请求数据的技术,而Comet是一种服务器向页面推送数据的技术。Comet能够让信息近乎实时的被推送到页面上。
Comet有两种实现方式:长轮询(是短轮询的翻版)和流

  • 短轮询
    浏览器定时向服务器发送请求,看有没有更新的数据。


    短轮询
  • 长轮询
    页面发起一个到服务器的请求,然后服务器一直保持连接打开,直到有数据可发送。发送完数据之后,浏览器关闭连接,随即又发起一个到服务器的新请求,页面打开期间一直持续不断。


    长轮询
  • HTTP流
    流不同于轮询,它在页面的整个生命周期内只使用一个HTTP连接,就是浏览器向服务器发送一个请求,而服务器保持连接打开,周期性向浏览器发送数据。


3.4 SSE 服务器发送事件

是支持短轮询,长轮询,HTTP流的API,实现Comet就容易很多。


  • EventSource对象
    readyState属性:0,表示正在连接到服务器,1表示打开了连接,2表示关闭连接。
    三个事件:



    服务器返回的数据以字符串的形式保存在event.data中。

let source=new EventSource("myevents.php");
source.onmessage=function(event){
    var data=event.data;
}
3.5 Web Sockets

在一个单独的持久连接上提供全双工、双向通信。

  • WebSocket对象


readyState属性:表示当前状态



send()方法:只能发送纯文本数据,复杂的数据必须序列化。



事件:
message事件,当服务器向客户端发来消息时触发。


  • SSE与Web Sockets选择
    1.是否有自由度建立和维护Web Socket服务器
    2.是否需要双向通信。如果只需读取服务器数据,SSE容易实现,如果必须双向通信(聊天室),
    选择Web Sockets
3.6 安全

可以通过XHR访问的任何URL也可以通过浏览器或服务器来访问。


图片.png

XSS:跨站脚本攻击
别人的js代码在你的页面里面执行。

get :数据放在url传输 数据量小 缓存 作为表单提交看得见参数
post:数据在body中传输 数据量大 不缓存 作为表单提交看不见

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容