原生Ajax总结

作者: fenerchen | 来源:发表于2018-03-08 16:31 被阅读47次

    AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。

    AJAX 不是新的编程语言,而是一种使用现有标准的新方法。

    AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。

    AJAX 不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。

    AJAX技术的核心是XMLHTTPRequest对象(XHR),虽然名字中有XML,但是Ajax通信与数据格式无关。

    创建XHR对象

    IE7+、Firefox、Opera、Chrome 和Safari 都支持原生的XHR 对象,使用XMLHttpRequest构造函数。

    var xhr=new XMLHttpRequest();//高版本
    

    那么重点来了,我想要支持低版本的IE,那得怎么使呢,不着急,有妙招
    首先检测原生XHR对象是否存在,如果存在则返回新实例。如果对象不存在,检查ActiveX对象。若都没有,那么,呵呵错误走你!

    function createXHR() {
        if (typeof XMLHttpRequest != 'undefined') {
            return new XMLHttpRequest(); //高版本
        } else if (typeof ActiveXObject != 'undefined') { //IE低版本
            if (typeof arguments.callee.activeXString != 'string') {
                var versions = ['MSXML2.XMLHttp.6.0', 'MSXML2.XMLHttp.3.0', 'MSXML2.XMLHttp'],
                    i, len;
                for (i = 0, len = versions.length; i < len; i++) {
                    try {
                        new ActiveXObject(versions[i]);
                        arguments.callee.activeXString = versions[i];
                        break;
                    } catch (ex) {
                        //跳过
                    }
                }
            }
            return new ActiveXObject(arguments.callee.activeXString);
        } else {
            throw new Error('No XHR object available');
        }
    }
    

    使用XHR

    在使用XHR对象时,必须调用open()方法,它有三个参数:要发送的请求类型(get、post)、请求的URL和表示是否异步。

    xhr.open('get','dom.php',false);//对dom.php的get请求,false同步
    

    open()方法并不会真正发送请求,而只是启动一个请求以备发送。通过send()方法进行发送请求,send()方法接受一个参数,作为请求主体发送的数据。如果不需要,必须填null,执行send()方法之后,请求就会发送到服务器上。

    xhr.send(null);//发送请求
    

    只能向同一个域中使用相同端口和协议的URL发送请求。如果URL与启动请求的页面有任何差别,都会引发安全错误。
    当请求发送到服务器端,收到响应后,响应的数据会自动填充XHR对象的属性。共有四个属性:

    属性名 说明
    responseText 作为响应主体被返回的文本
    responseXML 如果响应主体内容类型是‘text/xml’或'application/xml ,则返回包含响应数据的XML DOM文档。
    status 响应的HTTP状态
    statusText HTTP状态说明

    接受响应之后,第一步检查status属性,以确定响应已经成功返回。一般200为成功。

    已定义范围 分类
    1xx 100-101 信息提示
    2xx 200-206 成功
    3xx 300-305 重定向
    4xx 400-415 客户端错误
    5xx 500-505 服务器错误
    HTTP状态码 状态字符串 说明
    200 ok 服务器成功返回了页面
    301 永久转移
    302 found 资源暂时转移,常用于短连接转长连接
    304 Not Modified 请求的资源没有被修改,允许直接使用浏览器中缓存的版本
    400 Bad Request 语法错误导致服务器不识别
    401 Unauthorized 请求需要用户认证
    403 Forbidden 拒绝提供服务,可能发生在用户没有输入验证码的情况下
    404 Not found 指定的URL在服务器上找不到
    500 Internal Server Error 服务器遇到意外错误,无法完成请求
    502 Bad Gateway 网关错误
    503 ServiceUnavaliable 由于服务器过载或维护导致无法完成请求
    xhr.open("get", "example.txt", false);
    xhr.send(null);
    if((xhr.status>=200&&xhr.status<300)||(xhr.status==304)){
        alert(xhr.responseText);
    }else{
        alert(alert("Request was unsuccessful: " + xhr.status);
    }
    

    以上同步调用,简单,但是真正需要的是异步调用。使用异步调用的时候,需要触发readystatechange事件,然后检测readyState的属性即可。

    readyState值 状态 说明
    0 未初始化 尚未调用open(方法)
    1 启动 已经调用open()方法,但尚未调用send()方法
    2 发送 已经调用send(),但尚未接受响应
    3 接受 已经接受到部分响应数据
    4 完成 已经接受到全部数据,而且可以使用
    var xhr = createXHR();
    xhr.onreadystatechange = function() {
            if (readyState === 4) {//异步监控
                if ((xhr.status >= 200 && xhr.status < 300) || (xhr.status == 304)) {
                    alert(xhr.responseText);
                } else {
                    alert(alert("Request was unsuccessful: " + xhr.status);
                    }
                }
            };
    
    xhr.open("get", "example.txt", true);//异步
    xhr.send(null);
    

    使用abort()方法可以取消异步请求,放在send()方法之前会报错。放在responseText
    之前会得到一个空值。

    get与post

    首先来了解一下http头部信息,包含服务器返回的响应头信息和客户端发送出去的请求头信息。我们可以获取响应头信息或者设置 请求头信息。

    名称 含义
    Accept 浏览器能够处理的内容类型
    Accept-Charset 浏览器能够显示的字符集
    Accept-Encoding 浏览器能处理的压缩编码
    Accept-Language 浏览器当前设置的语言
    Connection 浏览器与服务器之间的连接类型
    Cookie 当前页面设置的任何Cookie
    Host 发出请求的页面所在的域
    Referer 发出请求的页面的URL
    User-Agent 浏览器的用户代理字符串
    //使用getResponseHeader()获取单个响应头信息
    alert(xhr.getResponseHeader('Content-Type'));
    //使用getAllResponseHeaders()获取整个响应头信息
    alert(xhr.getAllResponseHeaders());
    //使用setRequestHeader()设置单个请求头信息
    xhr.setRequestHeader('MyHeader', 'Lee'); //放在open 方法之后,send 方法之前
    

    我们只可以获取服务器返回回来响应头信息,无法获取向服务器提交的请求头信息,自然定义的请求头,在Js端无法获取

    get请求

    get请求常用于向服务器查询某些信息。必要时,可以将查询字符串参数追加到URL的末尾,以便提交给服务器。
    xhr.open('get','demo.php?rand='+Math.random()+'&name=koo',true)
    通过URL后的问号给服务器传递键值对数据,服务器接收到返回响应数据。特殊字符
    传参产生的问题可以使用encodeURIComponent()进行编码处理,中文字符的返回及传参,
    可以将页面保存和设置为utf-8 格式即可。

    function addURLParam(url, name, value){
        url+=(url.indexOf('?')==-1?'?':'&');//判断的url 是否有已有参数
        url+=encodeURLComponent(name)+'='+encodeURLComponent(value);
        return url;
    }
    

    post请求

    post请求可以包含非常多的数据,我们在使用表单提交的时候,大多使用post传输方式。
    xhr.open('post','demo.php',true);
    而发送post请求的数据,不会跟在url的尾巴上,而是通过send()方法向服务器提交数据
    xhr.send('name=lee&age=18')
    一般来说,向服务器发送post请求由于解析机制的原因,需要进行特别的处理。因为post请求和web表单提交不同,需要使用XHR来模仿表单提交。
    xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded')
    从性能上来讲post请求比get请求消耗更多一些,用相同数据比较,get最多比post块2倍

    封装ajax

    function ajax(obj) {
    var xhr = new createXHR();
    obj.url = obj.url + '?rand=' + Math.random();
    obj.data = params(obj.data);
    if (obj.method === 'get') obj.url = obj.url.indexOf('?') == -1 ?
    obj.url + '?' + obj.data : obj.url + '&' + obj.data;
    if (obj.async === true) {
    xhr.onreadystatechange = function () {
    if (xhr.readyState == 4) callback();
    };
    }
    xhr.open(obj.method, obj.url, obj.async);
    if (obj.method === 'post') {
    xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    xhr.send(obj.data);
    } else {
    xhr.send(null);
    }
    if (obj.async === false) {
    callback();
    }
    function callback () {
    if (xhr.status == 200) {
    obj.success(xhr.responseText); //回调
    } else {
    alert('数据返回失败!状态代码:' + xhr.status + ',
    状态信息:' + xhr.statusText);
    }
    }
    }
    //调用ajax
    addEvent(document, 'click', function () { //IE6 需要重写addEvent
    ajax({
    method : 'get',
    url : 'demo.php',
    data : {
    'name' : 'Lee',
    'age' : 100
    },
    success : function (text) {
    alert(text);
    },
    async : true
    });
    });
    //名值对编码
    function params(data) {
    var arr = [];
    for (var i in data) {
    arr.push(encodeURIComponent(i) + '=' + encodeURIComponent(data[i]));
    }
    return arr.join('&');
    }
    

    参考资料:JavaScript高级程序设计(第3版)

    相关文章

      网友评论

        本文标题:原生Ajax总结

        本文链接:https://www.haomeiwen.com/subject/prwsfftx.html