美文网首页
Ajax的核心---XMLHttpRequest

Ajax的核心---XMLHttpRequest

作者: BigDipper | 来源:发表于2020-07-17 15:12 被阅读0次

⛽ 概述

XMLHttpRequest对象的作用是与服务器交互,在不刷新页面的情况下请求特定 URL,获取数据。其实说白了,就是用异步的方式,向服务端发起请求,获取或提交数据,如果非要用通俗又粗俗的话说,它就是用来发ajax请求的

  • 其实XMLHttpRequest对象也能发送同步请求,只要把open()方法的第三个参数设置成false,就行。
    只是由于同步会对用户体验产生负面影响,浏览器都已经把在主线程上的同步请求弃用了。所以,只要记住XMLHttpRequest对象只能发送异步请求就对了。

  • XMLHttpRequest的通信流程是由客户端发起的。
    如果需要由服务端发起向客户端的推送,可以用server sent events这里是大神的教程)。
    如果需要全双工的通信,WebSocket这里还是大神的教程)可能是更好的选择。

🚥 运转流程

首先,先创建一个XMLHttpRequest实例:

const XHR = new XMLHttpRequest();

然后,调用open()方法:

const XHR = new XMLHttpRequest();

XHR.open('GET', '/apis');

这行代码会启动一个针对/apis地址(也可以是绝对路径)的GET请求,要说明的是:调用open()方法并不会真正发送请求,而只是启动一个请求以备发送。

要发送真正的请求,必须像下面这样调用send()方法:

const XHR = new XMLHttpRequest();

XHR.open('GET', '/apis');
XHR.send(null);

这里的send()方法接收一个参数,既要作为请求主体发送的数据。如果不需要通过请求主体发送数据,则必须传入null,因为这个参数对有些浏览器来说是必需的。

因为我们发送的是异步请求,所以要依据readyState属性的变化,来了解异步的过程。该属性表示请求/响应过程的当前活动阶段,如图所示:

readyState属性的变化.png

只要readyState属性的值由一个值变成另一个值,都会触发一次readystatechange事件。通常,我们只对readyState值为4的阶段感兴趣,因为这时所有数据都已经就绪。不过,必须在调用open()之前指定onreadystatechange事件处理程序才能确保跨浏览器兼容性。

const XHR = new XMLHttpRequest();

XHR.onreadystatechange = () => {
    if (XHR.readyState === 4) {
        // blah blah blah...
    } else { }
}

XHR.open('GET', '/apis');
XHR.send(null);

服务端接收到请求信息,并做出响应(如果通信正常),客户端在收到响应后,响应的数据会自动填充XHR对象的属性,比如:status(响应的HTTP状态)、responseText(作为响应主体被返回的文本)......。

一般来说,可以将HTTP状态码为200作为成功的标志。此外,状态代码为304表示请求的资源并没有被修改,可以直接使用浏览器中缓存的版本,当然,也意味着响应是有效的。

const XHR = new XMLHttpRequest();

XHR.onreadystatechange = () => {
    if (XHR.readyState === 4) {
        if (XHR.status < 300 || XHR.status === 304) {
            // blah blah blah...
        } else {
            alert(`请求失败了:${XHR.status}`);
        }
    } else { }
}

XHR.open('GET', '/apis');
XHR.send(null);

此处要说明一下:状态码为304的意思是说浏览器可以用缓存的版本,但是不代表浏览器没有向服务端发起请求。其实,浏览器是真真正正地向服务端发了请求的,只是服务端验证了资源的过期时间后,仅仅是告诉浏览器:“我就不给你数据了,你用你自己那份资源吧,还在保质期呢。”

另外,在接收到响应之前还可以调用abort()方法,来取消异步请求。在终止请求后,由于内存原因,还应该对XHR对象进行解引用操作。

上面,是使用XMLHttpRequest的最简单流程。

下面,再补充一些细节操作:

  • 添加/获取头部信息

每个HTTP请求和响应都会带有相应的头部信息(有的有用,有的对开发人员没用),XMLHttpRequest对象也提供了操作这两种头部(即请求头部和响应头部)信息的方法。

XMLHttpRequestsetRequestHeader()方法可以设置自定义的请求头部信息,要成功发送请求头部信息,此方法必须在调用open()方法之后且调用send()方法之前调用。

调用XMLHttpRequestgetResponseHeader()方法并传入头部字段名称,可以取得相应的响应头部信息。而调用getAllResponseHeaders()方法则可以取得一个包含所用头部信息的长字符串。这两个方法也要在调用open()方法之后且调用send()方法之前调用。

const XHR = new XMLHttpRequest();

XHR.onreadystatechange = () => {
    if (XHR.readyState === 4) {
        if (XHR.status < 300 || XHR.status === 304) {
            // blah blah blah...
        } else {
            alert(`请求失败了:${XHR.status}`);
        }
    } else { }
}

XHR.open('GET', '/apis');

XHR.setRequestHeader('请求头的自定义字段名称', '头部字段的值');
XHR.getResponseHeader('响应头的字段名称');
XHR.getAllResponseHeaders();

XHR.send(null);

为什么要添加/获取头信息呢?

此之目的仅仅是为了方便信息的传输。服务器在接收到自定义的头部信息后,可以执行相应的后续操作;同样的,在服务端,也可以利用头部信息向浏览器发送额外的、结构化的数据。而且,不是每次请求都必须做这种操作,要看使用场景,需要用的时候再用。

  • 监测进度

XMLHttpRequest提供了各种在请求被处理期间发生的事件以供监听。这包括定期进度通知、 错误通知,等等。

const XHR = new XMLHttpRequest();

/**
 * 监听请求过程中的各种事件
 */

XHR.onprogress = (oEvent) => {
    // 服务端到客户端的传输进程(下载)
    // 此时readyState=2

    if (oEvent.lengthComputable) {
        const percentComplete = oEvent.loaded / oEvent.total * 100;

        // blah blah blah...
    } else {
    // 总大小未知时不能计算进程信息
    }
};

XHR.onload = (oEvent) => {
    // 传输完成,所有数据保存在response中。
    // 此时readyState=4

    // blah blah blah...
};

XHR.onerror = (oEvent) => {
    // 当request遭遇错误时触发。

    // blah blah blah...
};

XHR.onabort= (oEvent) => {
    // 当request被停止时触发。

    // blah blah blah...
};

XHR.onreadystatechange = () => {
    if (XHR.readyState === 4) {
        if (XHR.status < 300 || XHR.status === 304) {
            // blah blah blah...
        } else {
            alert(`请求失败了:${XHR.status}`);
        }
    } else { }
}

XHR.open('GET', '/a.txt');
XHR.send(null);

你需要在请求调用open()之前添加事件监听。否则progress事件将不会被触发。

progress事件同时存在于下载和上传的传输。上面的例子是针对下载的相关事件。上传相关事件在 XMLHttpRequest.upload对象上被触发,像下面这样:

var oReq = new XMLHttpRequest();

oReq.upload.addEventListener("progress", updateProgress);
oReq.upload.addEventListener("load" , transferComplete);
oReq.upload.addEventListener("error", transferFailed  );
oReq.upload.addEventListener("abort", transferCanceled);

oReq.open();

🚗 示例

  • 🧪 发送一个GET请求
const XHR = new XMLHttpRequest();

XHR.onreadystatechange = () => {
    if (XHR.readyState === 4) {
        if (XHR.status < 300 || XHR.status === 304) {
            console.dir(XHR.response);
        } else { }
    } else { }
}

XHR.open('GET', '/apis');
XHR.send(null);

结果如图所示:


没有参数的GET请求.png

给请求加点参数:

XHR.open("GET", "/apis?ab=13&page=1");
XHR.setRequestHeader('CC', 989);
XHR.send(null);

结果如图所示:


有参数的GET请求.png
  • 🧪 发送一个POST请求
const XHR = new XMLHttpRequest();

XHR.onreadystatechange = () => {
    if (XHR.readyState === 4) {
        if (XHR.status < 300 || XHR.status === 304) {
            console.dir(XHR.response);
        } else { }
    } else { }
}

XHR.open('POST', '/apis');
XHR.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
XHR.send('name=张三丰&职务=掌门');

结果如图所示:


POST请求.png

为什么要添加Content-Type请求头信息呢?

需要设置Content-Type头信息,完全是由于服务端的原因。因为无论是表单、Ajax、jsonp,到了服务端那儿,它只认一种请求,就是form表单请求,所以Ajax发送的POST请求,服务端会认成是form表单的POST请求,而form表单发送POST请求时,如果不设置enctype属性,就会以默认的application/x-www-form-urlencoded方式提交表单,因此不加不行啊。

如果要上传文件,需要将Content-Type头的值设置为multipart/form-data,总之,跟form表单的提交方式保持一致就对了。

这篇《Express.js 解析 Post 数据类型的正确姿势》介绍了POST请求的四种方式,值得一看👏。

好了,先写到这儿吧。

--(完)--

相关文章

  • 学习封装ajax

    Ajax的核心 Ajax的实现核心就是XMLHttpRequest对象,浏览器通过XMLHttpRequest对象...

  • axios、 fetch、ajax

    一、ajax 传统 Ajax 指的是 XMLHttpRequest(XHR),核心使用XMLHttpRequest...

  • javascript 和 jQuery 的Ajax 用法

    ajax技术的核心是XMLHttpRequest对象(简称XHR) ajax通过原生的XMLHttpRequest...

  • AJAX

    ajax XMLHTTpRequest对象是Ajax的核心,XMLHTTpRequest对象使得js脚本能够实现对...

  • JS Ajax

    Ajax的核心是XMLHttpRequest对象 XMLHttpRequest对象 跨域资源共享问题 Ajax的扩...

  • 使用js实现AJAX和JSONP

    ajax的核心是XMLHttpRequest。一个完整的AJAX请求步骤:实例化XMLHttpRequest对象,...

  • ajax

    替换 ajax的原理 XMLHttpRequest 是ajax的核心 GET POST ajax状态码 HTTP状...

  • 2018-07-30

    js原声代码实现ajkx Ajax的核心是XMLHttpRequest对象 1、创建XMLHttpRequest对...

  • Ajax

    Ajax的技术核心是XMLHttpRequest 第一步:var xhr=new XMLHttpRequest()...

  • 运行环境

    Ajax运行环境 ajax核心XMLHttpRequest对象ActiveXObject 运行环境xampp(LA...

网友评论

      本文标题:Ajax的核心---XMLHttpRequest

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