Ajax you need to know

First, the concept of Ajax

  • Ajax is a technical solution , but not a new technology. It relies on the existing CSS/HTML/Javascript, and the core dependency is the XMLHttpRequest object provided by the browser, which enables the browser to issue HTTP requests and receive HTTP responses.
  • Ajax: Asynchronous JavaScript and XML
    • Asynchronous js: The code of js is executed from the beginning to the end. If a piece of code is not executed, the following code will not be executed. Asynchronous means that ajax can be executed out of order;
    • Ajax can not only process data in XML format, but also process data of json, array, and string type;
    • XML: A format for storing data:

      //XML的格式类型;
      <name>陈学辉</name>
      <age>18</age>
      <qq>356985332</qq>
      <email>[email protected]</email>
  • What can ajax do:

    A technology for data interaction between js and the backend, by requesting the negotiated interface to obtain the desired data

  • advantage

    When transmitting data, the server will be requested on this page without jumping the page, thereby reducing the pressure on the server. Real-time verification, reducing user rework and optimizing user experience

    2. Ajax data interaction process

  • Create an ajax object;

    var val=inputs[0].value;
    //下面这个是ajax对象;
    var ajax=new XMLHttpRequest;
  • Fill in the request address;
    ```
    //open is a method on the ajax object;

ajax.open("get","php/get.php?user="+val,true);

//The first parameter determines whether it is get or post;
//The second parameter is the request address, and the one to be submitted is added;
//The third parameter true means asynchronous, false means synchronous;

- 发送请求;

ajax.send();

- 等待服务器响应;

ajax.onload=function(){
//Accept the data after the response is completed;
span.innerHTML=ajax.responseText;
}

- 接收数据;
##三、返回的数据类型
> **ajax.responseText**这是服务器返回的值:
1.肯定是字符串,有的看起来是对象,其实是json的形式;
2.用JSON的方法:`JSON.parse(aja.responseText)`转成真正的对象就可以用对象操作的方法去操作了;
##四、XHR的兼容问题
- **XMLHttpRequest**是标准浏览器下的升级版本,IE6这些浏览器不支持;
- IE6下用**ActiveXObject(Microsoft.XMLHTTP)**

//Write a compatibility function to achieve cross-browser;
var ajax=null;

if(window.XMLHttpRequest){
ajax=new XMLHttpRequest;
}else{
ajax=new ActiveXObject(Microsoft.XMLHTTP)
};

##五、get和post的区别
- get方式
    - 通过地址栏信息进行数据传输,传输的大小有限制;
    - 不安全,用户的所有信息都会暴露出来;
    - 拼接数据的时候要用`encodeURI`转一下码,不然有中文就会乱码;
        > `encodeURI`把文字转成符号;
`decodeURI`把符号转成文字;
    - 不用设置请求头;
    - 数据拼接在open方法里;
    - 会有缓存问题;
- post方式
    - 通过send向服务器传输数据,理论上来说是没有长度或体积限制;
    - 相对来说安全,因为不直接暴露用户信息;
    - 不用转码,已经通过请求头设置了数据格式,不会有乱码;
    - 数据要拼接在send方法里;
    - 没有缓存问题
    - 在send()的前面需要设置一个请求头(不设置要出错);

ajax.setRequestHeader('Content-Type','application/x-www-form-urlencoded');

//Create an object;
var ajax=null;
if(window.XMLHttpRequest){
ajax=new XMLHttpRequest;
}else{
ajax=new ActiveXObject(Microsoft.XMLHTTP)
};
//Fill in the request address;
ajax.open("post", "php/post.php",true);
//To send a request, set the request header before send;
ajax.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
ajax. send("user="+val)
//The following steps are the same as the get method;

##六、同步与异步
- 同步
> 1、当`send()`方法调用后会等待服务器返回信息,如果服务器一直没有响应,就会阻塞后面的代码,后面的代码就不会执行
2、后面的代码执行受前面代码的影响,前面的代码没跑通,后面的代码就不会执行
- 异步
>> 1、当`send()`方法调用后,就会执行后面的代码,不用等待服务器的响应
2、后面的代码执行不受前面代码的影响
##七、onreadystatechange与onload
- `ajax.readState`ajax的运行步骤(第一步捕捉不到)
    - 它的值为4的话说明AJAX已经运行完毕;
    - *0* 代表初始化,还没调用**open**方法;
    - *1* 代表载入,已经调用**send**方法,正在发送请求;
    - *2* 代表载入完成,send方法已完成,已收到全部响应内容;
    - *3* 代表正在解析响应内容;
    - *4* 代表响应完成,可以在客户端调用了;
- `ajax.status`(状态码)
    - 200是成功的;
    - 404是错误的;
- `onreadStateChange`
> `readstate`的值发生变化就会触发这个事件;
- `onload`
> >所有请求成功完成后触发,此时的`readstata`的值为**4**
**IE(6,7,8)不支持**
**现在这个方法逐渐取代`onreadstatechange`这个方法了**

ajax.onreadstatechange=function(){
if(ajax.readstate==4){ //The response of the service area is completed;
if(ajax.status==200){ //The server is normal;
//The code to be executed is placed here;
}
}
}

##八、封装ajax函数
> 封装ajax函数,传进函数里面的参数其实是一个**对象**;

- 对象中包包含以下几种数据,包含在一个对象里面:
    - URL:发送请求的地址,需要把请求发给谁;
    - method:发送请求的方法:get或者post;
    - dataType:响应之后返回的数据类型:JSON,XML,STRING;
    - data:请求的时候传的数据(它是一个对象需要处理格式);
    - succ:成功之后的callback;
    - fail:失败后的callback;

function ajax(json){
//默认参数;
var settings={
url:"",
method:"get",
data:{},
dataType:"json",
succ:null,
fail:null
}

//用户传的参数覆盖默认参数;
for (var attr in json){
    settings[attr]=json[attr];
}

//把data拼成正确的格式;
var arr=[];
for (var attr in settings.data){
    arr.push(attr+"="+settings.data[attr]);
}
settings.data=arr.join("&");

//声明变量;
var ajax=window.XMLHttpRequest?new XMLHttpRequest():ActiveXObject("Microsoft.XMLHTTP");

//设置请求方式;
//请求地址里面的new Date()方法,是为了设置不同的时间戳去解决缓存的问题;
if(settings.method.toLocalLowCase==="get"){
    ajax.open("get",settings.url+"?"+settings.data+"&"+new Date().getTime(),true);
    ajax.send();
}else{
    ajax.open("post",settings.url,true);
    //注意要设置一个请求头;
    ajax.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
    ajax.send(settings.data);
}

//设置完成时间的兼容性;IE6下是没有ajax.onload方法的;
if(typeof ajax.onload==="undefined"){
    ajax.onreadystatechange=ready;
}else{
    ajax.onload=ready;
}

//封装一个ready()函数;
function ready(){
    if(ajax.readystate==4){
        if(ajax.status==200){
            //用一个switch判断返回值得类型;
            switch(settings.dataType.toLocalLowCase()){
                case "string"   : 
                    settings.succ(ajax.responseText);
                    break;
                case "json"     :
                    //把responsetext转成json格式;
                    setting.succ(JSON.parse(ajax.responseText));
                    break;
                case "xml"      :
                    settings.succ(ajax.responseXml);
                    break;
            }
        }else{
            settings.fail(ajax.status);
        }
    }
}

}

> 要注意第**57**行的**JSON.parse**在低版本的浏览器中是不兼容的,需要下载一个**json2.js**的文件解决这个问题;

##九、ajax上传
- 上传只能用 **post** 的方法,后台要处理中文相关的问题;
- ajax.upload.onprogress 上传的进度事件;就是上传的时候要做的事情;
    - `ev.loaded` 已经上传的文件大小;
    - `ev.total` 总的文件大小;
    > 通过这个可以做出来一个上传的进度条;
用H5中的`<progress></progress>`这个API;
- **files** 上传的选中的文件列表;
    >>1.包括文件大小、类型、最后修改的时间等等;
        2.放在`type="file"`的表单空间中;
- FormData 用来创建与表单格式相同的数据,它是XHR的二级定义,是一个**二进制**的数据;**低版本的浏览器不支持**;
>>> **我自己对于FormData的理解:
FormDate可以new出来一个实例,这个实例可以继承它身上的append方法;这个操作放在`ajax.open`和`ajax.send`之间**

var formdata=new FormData();

//下面通过循环把选中的文件里面的额东西添加到这个对象身上;

for(var i=0;i<inputs[0].files.length;i++){

//inputs[0]指的是一个type="file"的表单控件;

formdata.append("file",inputs[0].files[i]);

}

//这时候formdata就可以被发送给服务器了,前面加上一个请求头;
##十、跨域的问题
- 概念:
> 两个不同域名下的数据进行交互。Ajax之所以不能跨域其实是因为XMLHttpRequest受到**同源策略**的限制,只能让它访问同源下的数据,不能访问不同源下的数据;
- 同源策略:
>> 每个网站只能读取同一来源的数据,这里的同一来源指的是主机名(**域名**)、**协议**(http/https)和**端口号**的组合。在没明确授权的情况下,不能读写对方的资源,它是浏览器最核心也最基本的安全功能;
**只要有一个不一样就跨域;**
- 解决跨域的方法:
    - 在标准浏览器下XMLHttpRequest配合后端设置一个请求权限,在php里写上 header('Access-Control-Allow-Origin:*');
    - 服务器代理,缺点是后端开发的成本大;
    - iframe、flash、postMessage、WebSocket;
    
>>> 这些方法都不是最优的,下面提供一种方法叫做 **jsonp**

##十一、jsonp
- jsonp的概念(json+padding)
    - 通过script标签引入某些数据,是同步模式的,用script标签做跨域的时候,不建议将数据提前加载,需要**按需加载**;
    - 当需要数据的时候创建一个script标签,将需要的数据放在src中,通过onload去监听是否请求过来,请求完毕就调用传回来的数据(异步加载);
    - jsonp不能用post请求,只能是get请求;
> 带src属性的<script><img><iframe><link>等标签是不需要遵守同源策略的,但是通过src加载的资源,浏览器限制了javascript的权限,**能读不能写**;这就是jsonp能实现跨域的原因;
- jsonp中的回调函数
    - 通过jsonp的方式的数据一般都会放在一个回调函数里;
    - 请求到的结果是这样的`getData({"color":["red","green","blue"]})`
        - 数据放在函数的参数里,可以是任何数据形式(对象、数组)
        - 回调函数的名字要么是后端定死的,要么是我们在请求地址跟动态加上的


>> 注意**callback**是要设置成全局的,要不就放在操作的前面;

- 封装一个jsonp

function jsonp(obj){
var settings={
url:'', //address
data:{}, //data to be sent
callBack:'callback', //the variable
fnName:'jsonp_' that stores the name of the callback function in the url +new Date().getTime(), //name of callback function
succ:function(){} //callback function for successful request
};

for(var attr in obj){
    settings[attr]=obj[attr];
}

//创建一个script标签
var script=document.createElement("script");
script.className='sc';
settings.data[settings.callBack]=settings.fnName;

var head=document.getElementsByTagName('head')[0];


//把要传的数据拼起来
var arr=[];         //['wd=sds','cb=jQuery1']
for(var attr in settings.data){
    arr.push(attr+'='+settings.data[attr]);
}
settings.data=arr.join('&');
script.src=settings.url+'?'+settings.data;

head.appendChild(script);

//把回调函数挂载到window身上
window[settings.fnName]=function(data){
    //当调用这个函数的时候,先把页面中所有的已经请求过的script删掉
    var scripts=head.getElementsByTagName('script');
    for(var i=0;i<scripts.length;i++){
        if(scripts[i].className=='sc'){
            head.removeChild(scripts[i]);
        }
    }
    
    settings.succ(data);
};

}
```

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324684743&siteId=291194637