Ajax与Comet

Ajax的主要作用是实现在不刷新页面的情况下实现局部异步更新数据。

原生js实现ajax请求代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
//get请求方式
var xmlhttp
function xml(){
if(window.XMLHttpRequest){
xmlhttp=new XMLHttpRequest();
}else{
xmlhttp=new ActicveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function(){
if(xmlhttp.statue==200&&xmlhttp.readyState==4){
var responseText=JSON.parse(xmlhttp.responseText);
//这里返回数据后的处理过程了,我就不写了
........
}
}
 xmlhttp.open("GET","http://www.baidu.com",true);//第三个参数表示时候异步,true就是异步
 xmlhttp.send(null);//这里面可以传递一个参数,如果不要作为请求主体发送的数据,就不需要加上这个参数,这个参数需要序列化之后才能传进去,即stringify
}

//POST请求
function xml(){
if(window.XMLHttpRequest){
xmlhttp=new XMLHttpRequest();
}else{
xml=new ActicveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function(){
if(xmlhttp.statue==200&&xmlhttp.readyState){
var responseText=JSON.parse(xmlhttp.responseText);
//这里返回数据后的处理过程了,我就不写了
........
}
}
 xmlhttp.open("POST","http://www.baidu.com",true);//第三个参数表示时候异步,true就是异步
 xmlhttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded");//如果是post请求的话就得加上这一句,因为加上这一句的就可以像表单一样获取到对应的参数,比如在php中就可以通过$_post这个超级全局变量获取到信息,如果不加这一句的话就在再$_post找不到数据
 xmlhttp.send(null);//这里面可以传递一个参数,如果不要作为请求主体发送的数据,就不需要加上这个参数,这个参数需要序列化之后才能传进去,即stringify
}

readyState各状态代表什么

  • 0:未初始化,尚未调用open()方法
  • 1:启动,已经调用open方法,尚未调用send方法
  • 2:发送,已经抵用send方法,尚未收到响应
  • 3:接收,已经接收到部分数据,
  • 4:接收全部完成

    JQuery实现ajax请求

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    $.ajax({
    type:"POST",
    url:"/api",
    data:{
    name:"chen",
    age:"bibi"
    },
     dataType:"json", //可以死json,xml,string
     async:true, //默认true
     success:function(data){
       //这里的data不用通过JSON.parse转化了
     },
     error:function(xhr,status,errorThrown){
       console.log(xhr.state);//获取到错误码400等
    console.log(xhr.responseText);
       console.log(xhr.readyState);//状态1,2,3,4
    console.log(status);//null, timeout, error, abort, parsererror
    console.log(errorThrown);//收到http出错文本,如 Not Found 或 Internal Server Error
     }
     complete:function(xhr,status){
    //第一个参数
    console.log(xhr.responseText);//这里返回的值跟success返回的data值是一样的,它还可以xhr.status xhr.readyState
       //第二个参数表示的是success或者error
       console.log(status);//success,notmodified,nocontent,error,timeout,abort,parsererror
    if(status=="timeout"){
    var xmlhttp=window.XMLHttpRequest?new window.XMLHttpRequest():new ActiveXObject("Microsoft.XMLHttp");
         xmlhttp.abort();//中断请求
         $("#a").html("请求超时");
      }
     },
     beforeSend:function(){
       //这个是最先执行的,如果spiner图片可以在数据为拿到之前显示这个图片
     },
     cache:false //如果数据经常变化的话就最好设置成false
    })

JQuery的get请求

1
2
3
4
5
6
7
//第二个参数会在执行过程中自动加到/api后面,即/api?action=get&name=chen
//$.get(url,[data],[callback])

$.get("/api",{action:"get",name:"chen"},function(data,textStatus){
//如果成功的话textState的值是success,只有成功才能进入这个回调函数
 console.log(data);
})

JQery单个post方式请求

1
2
3
4
5
6
//$.post(url,[data],[callback],[type]) type是客户端请求的类型json,xml等

$.post("/api",{action:"get",name:"chen"},function(data,textStatus){
//如果成功的话textState的值是success,只有成功才能进入这个回调函数
 console.log(data);
})

Ajax上传文件可以通过FormData

因为有时候表单提交可能需要提交附件,那么如果用ajax普通方式来提交的话就会出现问题,因为form表单默认的编码方式是application/x-www-form-urlencoded,这种编码方式只能编码文本类型的数据,因此Ajax发送请求的时候,会把data序列化成 一个个String类型的键值对,此种传输数据的方式能够满足大部分应用场景,然而当传输的数据里有附件的时候,此序列化机制便是我们的绊脚石。FormData是html5的接口,使用它一行代码便可以拿到整个form表单对象:var form = new FormData(document.getElementById("form")),记住,如果不是用document.getElementById("form")获取数据,而是通过$("#form")[0]切记切记要在后面加上这个[0],这是我踩过的坑,太狗血了。我们拿着获取到的这个form对象,去赋给Ajax的data,并且阻止它将参数转成成String类型的键值对,此举需要设置processData属性为false,此属性默认为true;同时设置Ajax的编码方式为false(contentType: false),在form表单里已经设置了编码方式,Ajax的编码机制已经不需要,这样我们就可以用Ajax去提交一个form对象,从而解决表单有附件的问题。需要注意的是,务必将Ajax的提交方式,设置为post,get请求只能携带几kb的数据。若是不设置processData为false,去提交带附件的form同样是提交不上去的,它的序列化机制是硬伤。所以提交的时候,只能不使用它的序列化机制。用这个formdata可以不用再form表单的标签上设置enctype="multipart/form-data",话不多说,看代码吧

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var formData=new FormData($("#form")[0]);
$.ajax({
 url:'接口地址',
type:'post',
data:formData,
cache:false,
processData:false,
contentType:false,
success:function(data){
   .....写自己的东西
   }
error:function(xhr,status){
console.log(status);
}
})

上传文件

情景:一个表单里面有提交文件的表单字段,点击type=”file”后选择文件,可以多次点击选择不同的文件,然后先异步上传到服务器的临时目录也就是缓存目录,当点击提交表单的时候提交全部文件
做法:我们每次点击选择完文件后就触发一个ajax去上传文件到缓存目录,上传成功后我们就动态生成一个input[type=”checkbox”],并且将上传文件后返回的id的值赋值到checkout的value上,这样我们提交表单后后台可以通过复选框的这些id去缓存目录找到对应的文件然后上传到服务器的真实目录上。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<form>
<input type="file" id="uploadFile">
</form>
<script>
function uploadFile(){
var formData=new FormData();
formData.append("file",$("#uploadFile")[0].files[0]);
$.ajax({
url:'../../plugins/servlet/fileupload',
type:'post',
data:formData,
cache:false,
processData:false,//阻止它将参数转成string类型的键值对
contentType:false,//设置ajax的编码方式为false
success:function(data){
console.log($("#uploadFile")[0].files[0].name);
$(".uploadFile").append("<input type='checkbox' class='fileTemp' checked='checked' name='fileTemp' id="+data+" value="+data+">");
},
error:function(xhr,status){
console.log(status);
},
complete:function(XMLHttpRequest,xhr){
   //这里主要是来做进度条的
var tempID=XMLHttpRequest.responseText;
$(".pregressBar:last").attr("data-temp",tempID);
}
})
}
</script>
//这样的话每次选择文件都会触发一次ajax,每次都会动态添加一个input[type="checkbox"]
//我生成这个input也是为了做进度条的,每次点击都会触发这个ajax,还触发了另外一个实时获取进度条的ajax,另外一个ajax是通过setTimeout定时器来不断的发送请求获取进度百分比的,这个我就不在这里写了

JSON

概念:JavaScript的对象变现法
优点:读写速度快,简短,javascript内建的方法直接解析stringify和parse
注意:键值对必须用双引号,不能用单引号
json的值可以是:数组,对象,数字,字符串,null

  • JSON.parse()
    这个的作用是将JSON字符串'{"name":"chen"}'转换成javascript的json对象也就是普通的对象{name:"chen"},他可以传递一个参数,这个参数对每个键值对都会进行过滤筛选

    1
    2
    3
    4
    5
    6
    7
    8
    9
    var a={"name":"chen","age":12}
    var b=JSON.parse(a,function(key,value){
    if(key==="age"){
    value=14;
    }
    return value;
    })
    console.log(b);
    最后输出的是{name:"chen",age:14}
  • JSON.stringify()
    这个的作用是将对象转换成json字符串,也就是序列化的过程。可以传递其他两个参数,第一个参数是过滤器,可以是数组,也可以是一个函数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    var a={"name":"chen","age":12}
    //函数的时候
    var b=JSON.stringify(a,function(key,value){
    if(key==="age"){
    value=14;
    }
     return value;
    })
    console.log(b);
    最后输出的是{"name":"chen","age":14}

    //数组的时候
    var b=JSON.stringify(a,["name"]);
    console.log(b)
    最后输出的是{"name":"chen"}

    //第三个参数是字符串缩进
    var b=JSON.stringify(a,null,"--");
    console.log(b)
    最后输出的是
    {
    --"name":"chen",
    --"age":12
    }

JSON和XML的相互转换

需要下载:jquery / jquery.json2xml.js / jquery.xml2json.js

  • xml转换成json对象

    1
    2
    3
    4
    5
    6
    7
    8
    var str="";
    str+="<root>";
    str+="<name>chen</name>";
    str+="<age>32</age>";
    str+="</root>";
    var obj=$.xml2json(str);
    console.log(str);//结果是{name:"chen",age:32}
    var json=JSON.stringify(obj)//输出是{"name":"chen","age":32}
  • json对象转换成xml

    1
    2
    var a={name:"chen",age:43};
    $.json2xml(a);//输出是<root><name>chen</name><age>43</age></root>

GeoJSON和TopoJSON

测试工具:geojson.io
这两种是符合JSON数据格式的表示地理信息

  • GeoJSON
    1
    2
    3
    4
    {
     "type":"point", //表示点,LineString表示面
     "coordinates":[-105,39]
    }

跨域

当协议,子域名,主域名,端口号任意一个不同就是跨域
javascript的同源策略是对XHR的主要约束,他为通信设置了“相同的域、相同的端口、相同的协议”,视图访问上述限制外的资源会引发安全错误,那么就需要跨域解决方案,这个解决方案就是CORS(跨源资源共享) IE8通过XDR(XDomainRequest)对象支持CORS,其他浏览器通过XHR对象原生支持CORS。图像PING和JSONP也类似于CORS,也是解决跨域通信的技术。

解决跨域

  • 代理,主要是在后端人员操作,比如北京有一台服务器www.beijin.com 想访问上海服务器 www.shanhai.com 那么我们就只需要在在北京服务器上做一个代理服务器即与北京服务器是同源的www.beijin.com/prox 然后通过这个代理去访问上海服务器的数据,然后我们前端只需要获取数据只要访问www.beijin.com/prox 就好了
  • JSONP,可用于解决主流浏览器的跨域数据访问问题(不支持post请求,还有就是JSONP死是从其他域中加载代码执行,如果其他域不安全,那么web服务就不安全了)
    例子1
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    在www.aaa.com页面中声明一个函数
    <script src="http://www.bbb.com/jsonp.js"></script>
    <script>
    function jsonp(json){
    console.log(json["name"]);
    }
    </script>
    在www.bbb.com页面中
    jsonp({"name":"chen"})
    以上的执行时a域名声明,b域名调用

例子2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//前端
$.ajax({
type:"GET",
url:"/api",
data:{
name:"chen",
age:"bibi"
},
 dataType:"jsonp",//改成jsonp
 jsonp:"call",//call随便都可以
 success:function(data){

},
 error:function(xhr){
   console.log(xhr.state);//获取到错误码400等
 }
})

//后端php
$jsonp=$_GET["call"];
$result=$jsonp.'({"success":false,"msg":"错误"})'; //返回的数据必须用$.jsonp.({...})连接起来

  • XHR2

Comet

Ajax是一种从页面向服务器请求数据的技术,而Comet则是一种服务器向页面推送数据的技术
两种实现Comet的方式:长轮询和流。长轮询是传统轮询的翻版
长轮询和短轮询的区别
短轮询是服务器立即发送响应,无论数据是否有效,
长轮询是页面发起请求,服务器一直保持连接打开,知道有数据发送,发送完数据之后,浏览器关闭连接,随即又发起到一个到服务器的新请求
HTTP流,流不同于上述两种轮询,因为它在页面的整个生命周期内只使用一个HTTP连接,就是浏览器向服务器发送一个请求,而服务器保持连接打开,然后周期性的向浏览器发送数据

当前网速较慢或者你使用的浏览器不支持博客特定功能,请尝试刷新或换用Chrome、Firefox等现代浏览器