目 录CONTENT

文章目录

Ajax核心原理

Administrator
2020-07-24 / 0 评论 / 0 点赞 / 8054 阅读 / 10399 字

Ajax基础

当前端需要向后端请求数据的时候,我们有很多种方式 ,如表提交,websocket。今天我们再学习一种ajax

Ajax是一种异步数据通讯方法,它是由前端向服务器发送请求,服务器再返回一个响应给我

在window浏览器对象下面,有一个属性对象叫 XMLHttpRequest,它就是我们的ajax核心 ,它简称xhr

Ajax的初始化

Ajax的核心对象是XMLHttpRequest,但是这个对象有兼容性,所以我们要做兼容处理

var xhr = null;
if (window.XMLHttpRequest) {
    //说明是新版本的浏览器,或是以谷歌(webkit)为核心的浏览器
    //新版本的IE也具备这个属性了
    xhr = new XMLHttpRequest();
} else {
    //老版本的IE
    xhr = new ActiveXObject("Microsoft.XMLHTTP");
}

后面可以直接简写成下面的方式

var xhr=Window.XMLHttpRequest?new XMLHttpRequest():new ActivexObject("Microsoft.XMLHTTP")

建立请求过程

在监听Ajax状态变化之前,我们要建议请求

xhr.open(请求方式,请求url,异步/同步);
  • 请求方式常见的有"GET"和"POST"
  • 同步则是false,异步是true

同步会等待,异步会执行

xhr.open("get","http://www.xxx.com",true);   //发起一个异步请求

Ajax的请求状态变化

Ajax的请求状态有5个步骤

  1. 请求未初始化
  2. 服务器连接已建立
  3. 请求已接收
  4. 请求处理中
  5. 请求已完成,且响应已就绪

只请当请求的状态为4的时候,才说明请求已完成。在判断请求完成的时候,我们还要判断请求状态的状态码

  1. 500开头的服务器
  2. 200代表功能
  3. 404代表请求路径错误 ,找不到请求地址
  4. 403没有请求权限
  5. 304缓存
xhr.onreadystatechange = function () {
        // 请求状态为4并且状态码为200,则代表请求成功
        if (xhr.readyState == 4 && xhr.status == 200) {  
            console.log(typeof xhr.responseText); 
            //接口返回的是一个json字符串,那么,我们就可以通过JSON.parse去做一次转换,在jQuery里面它会自己做转换
            var obj=JSON.parse(xhr.responseText);
            console.log(obj); 
        }
    }

在DOM里面,事件的英文单词全小写

Ajax发送数据

xhr.send(参数);

当是post请求的时候,参数应该在send方法里面,当请求方式是get的时候,请求参数直接接在了请求地址的后面


Ajax注意事项

ajax的请求方式有两种,一种是get,一种是post。在不同的请求方式里面,它的配置是不一样的

关于get请求

get请求的注意事项如下

直接在浏览器里面输入地址,它也是一个get请求

  1. 它的请求参数直接拼在了请求地址的后面

    var url="https://www.softeem.xin/maoyanApi/ajax/detailmovie";   //这是请求地址
    var params="movieId=1277982";             //请求参数
    xhr.open("get",url+"?"+params,true);
    
  2. 因为get请求本质上面是通过浏览器的地址在拼接请求参数,所以它有大小限制,它不能够提交大量的数据到后台

    同时它还不能提交文件到后台,所以get请求只适合处于少量的文本数据参数

    get请求的参数会暴露在浏览器地址栏,这个时候,如果有敏感信息就会非常麻烦。所以它的安全性不高

关于post请求

post请求与get请求不一样,它主要的区别与注意事项如下

  1. post请求的时候,它的参数没有拼在URL地址后面,所以后期如果通过Ajax进行请求的时候,它需要在主动发送请求参数

    xhr.send(params);
    
  2. post请求要根据请求参数设置请求的header【请求头】

    var params="s_id=20190101&s_tel=18627104906";  //这是请求参数
    xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
    xhr.send(params);
    

    如果请求参数是一个对象的时候,则请求头又需要进行改变

    var params={
        s_id:"20190101",
        s_tel:"18627104906"
    }
    xhr.setRequestHeader("Content-Type","application/json");
    xhr.send(JSON.stringify(params));
    
  3. post请求与get主求相反,它可以提交大量的数据,只要后台不做限制【如果后台服务器做了限制,就以后台服务器为主】

    get只能提交少量的文本参数,但是post不仅可以提交大量的文本参数,还可以提交非文本类型的参数,例如文件(这个时候,它就不是文本参数,它是以流的形式提交的);

Ajax的封装

ajax是前端最常用的一个技术 ,前端可以借用于第三方框架(如 jQuery)去使用ajax,但是我们仍然需要掌握自己封装的技巧

第一个版本的封装

该版本是一个方法的版本,需要严格的对参数进行控制

function ajaxHelper(method,url,callBack,params){
    var xhr=window.XMLHttpRequest?new XMLHttpRequest():new ActiveXObject("Microsoft.XMLHTTP");
    xhr.open(method,url,true);
    xhr.onreadystatechange=function(){
        if(xhr.readyState==4&&xhr.status==200){
            if(typeof callBack=="function"){
                //调用这个回调方法,并且向这个回调方法里面传递一个实参
                callBack(xhr.responseText);
            }
        }
    }
    if(method.toUpperCase()=="GET"){
        xhr.send();
    }
    else if(method.toUpperCase()=="POST"){
        //首先判断params有没有值
        if(params){
            if(typeof params=="string"){
                xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
                xhr.send(params)
            }
            else if(typeof params=="object"){
                xhr.setRequestHeader("Content-Type","application/json");
                xhr.send(JSON.stringify(params));
            }
        }
        else{
            xhr.send();
        }
    }
}

现在我们对上面的版本进行测试

get测试

var url="https://www.softeem.xin/maoyanApi/ajax/detailmovie";   //这是请求地址
var params="movieId=1277982";             //请求参数

ajaxHelper("get",url+"?"+params,function(data){
    console.log(data);
});

测试结果正常

post测试

var url="http://www.softeem.xin:8086/StuInfo/checkLogin";
var params="s_id=20190101&s_tel=18627104906";
ajaxHelper("post",url,function(data){
    console.log(data);
},{
    s_id:"20190101",
    s_tel:"18627104906"
});

在这个POST里面,我们分别对参数做了两次处理,一次是params的字符串,一次是对象,这两次都正常

在上面的封装里面,它是一个方法的封装,但是我们希望能够像jQuery 里面一样进行getpost的请求,这个时候,我们可以像如下方式去封装

第二个版本

!function () {
    Object.defineProperty(window, "ajaxHelper", {
        configurable: false,
        enumerable: true,
        writable: false,
        // 使用了冻结对象
        value:Object.freeze({
            //初始化
            init: function (method, url, callBack) {
                var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
                xhr.open(method, url, true);
                xhr.onreadystatechange = function () {
                    if (xhr.readyState == 4 && xhr.status == 200) {
                        if (typeof callBack == "function") {
                            callBack(xhr.responseText);
                        }
                    }
                }
                return xhr;
            },
            //假设它的请求地址与请求参数是接在一起,拼成了URL
            get: function () {
                var url, params, callBack;
                if (arguments.length == 2) {
                    url = arguments[0];
                    callBack = arguments[1];
                } else if (arguments.length == 3) {
                    url = arguments[0];
                    params = arguments[1];
                    callBack = arguments[2];
                    if (typeof params == "string") {
                        url = url + "?" + params;
                    } else if (typeof params == "object") {
                        var str = "";
                        for (var i in params) {
                            if (params[i] instanceof Array) {
                                //是数组,再去遍历一次
                                for (var j in params[i]) {
                                    str += i + "=" + params[i][j] + "&";
                                }
                            } else {
                                str += i + "=" + params[i] + "&";
                            }
                        }
                        //去掉最后一个“&”
                        str = str.substr(0, str.length - 1);
                        url = url + "?" + str;
                    }
                }
                var xhr = this.init("get", url, callBack);
                xhr.send();
            },
            post: function () {
                var url, params, callBack;
                if (arguments.length == 2) {
                    url = arguments[0];
                    callBack = arguments[1];
                } else if (arguments.length == 3) {
                    url = arguments[0];
                    params = arguments[1];
                    callBack = arguments[2];
                }
                var xhr = this.init("post", url, callBack);
                //再来判断参数
                if (params) {
                    if (typeof params == "string") {
                        xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
                        xhr.send(params);
                    } else if (typeof params == "object") {
                        xhr.setRequestHeader("Content-Type", "application/json");
                        xhr.send(JSON.stringify(params));
                    }
                } else {
                    xhr.send();
                }
            }
        })
    })
}();
  1. 立即执行函数
  2. 对象特殊属性定义
  3. 冻结
  4. ajax基本使用以及参数格式的转换

Ajax的跨域问题

域是什么?origin,它包含协议,主机地址,端口号

在之前讲BOM里面的localStoragesessionStorage以及webSql等缓存的时候,我们都提过,这些东西都不能跨域访问


Ajax本质上面也是不能跨域的

例如我的页面地址是https://127.0.0.1:5500/1ajax.html,但是Ajax请求的地址是https://www.softeem.xin/maoyanApi/ajax/detailmovie,这个时候,就发生了跨域的现像,一旦跨域现象,浏览就会报错,报一个Access-Control-Allow-Origin

CORS:跨域资源共享

ajax如果想实现跨域资源的调用,最简单的方法就是服务器实现CORS,只需要后台服务器在返回的时候添加如下请求头就可以了

Access-Control-Allow-Headers: Content-Type
Access-Control-Allow-Methods: GET,POST,PUT,DELETE,OPTIONS
Access-Control-Allow-Origin: *
0

评论区