moonshot 5 - AJAX 3

139 阅读4分钟
  • XMLHttpRequest Level 2 在moonshot4 - AJAX 2中我们用原生的XMLHttpRequest对象发起了AJAX请求,但这个对象以及是旧版本了,它有着以下几个缺点:
  1. 只支持文本数据的传输,无法用来读取和上传文件
  2. 传送和接收数据时,没有进度信息,只能提示有没有完成 基于这些事实,我们引入XMLHttpRequest Level 2,显然它是XMLHttpRequest的升级版,它有着以下几点新功能:
  3. 可以设置HTTP请求的时限
let xhr = new XMLHttpRequest();
// 设置超时时间
xhr.timeout = 3000;
// 设置超时后的处理函数
xhr.ontimeout = function() {
    alert('请求超时了!');
};
xhr.open('GET', 'https://www.juejin.cn/Citzien7');
xhr.send();
xhr.onreadystatechange = function() {
    if (xhr.readyState === 4 && xhr.status === 200) {
        console.log(xhr.responseText);
    };
};
  1. 可以使用FormData对象管理表单数据 AJAX操作经常用来提交表单数据。为了方便表单处理,新增了一个FormData对象,可以模拟表单数据
// 1. 创建 FromData 实例
let fd = new FormData();
// 2. 调用 append 函数,向 fd 中追加数据
fd.append('uname', 'lee');
fd.append('id', '805741612');

let xhr = new XMLHttpRequest();
xhr.open('POST', 'https://www.juejin.cn/Citzien7');
xhr.send(fd);
xhr.onreadystatechange = function() {
    if (xhr.readyState === 4 && xhr.status === 200) {
        console.log(xhr.responseText);
    };
};

假设我们的网页HTML结构中有一个表单,那么我们可以用DOM操作获取这个表单,然后再结合FormData对象

// 获取表单元素
let form = document.querySelector('#form1');
// 当我们点击 submit 按钮时,利用 AJAX 提交表单数据
form.addEventListener('submit', function (e) {
    // 阻止表单提交的默认事件——提交与跳转网页
    e.preventDefault();
    // 根据 form 表单创建对象
    let fd = new FormData(form);
    
    let xhr = new XMLHttpRequest();
    xhr.open('POST', '...');
    xhr.send(fd);
    xhr.onreadystatechange = function () {...};
});
  1. 可以上传文件
// 1. 获取文件上传按钮
let btnUpload = document.querySelector('#btn1');
// 2. 为按钮绑定点击事件
btnUpload.addEventListener('click', function () {
    // 3. 获取用户选择的文件列表
    let files = document.querySelector('#file1').files;
    if (files.length <= 0) {
        return alert('请选择要上传的文件!'); // 若没有选择文件但点了上传
    }
    // 4. 实例化 FormData 对象
    let fd = new FormData();
    fd.append('avatar', files[0]);
    // 5. 发起 AJAX 请求
    let xhr = new XMLHttpRequest();
    xhr.open('POST', 'https://www.juejin.cn/Citizen7');
    xhr.send(fd);
    xhr.onreadystatechange = function () {
        if (xhr.readyState === 4 && xhr.status === 200) {
            console.log(JSON.parse(xhr.responseText));
        }
    }
});
  1. 可以获得数据传输的进度信息
let xhr = new XMLHttpRequest();
// 监听 xhr.upload 的 onprogress 事件,即当上传这个事件发生时
xhr.upload.onprogress = function (e) {
    // e.lengthComputable 是一个布尔值,表示当前上传的资源是否具有可计算长度
    if (e.lengthComputable) {
        // e.loaded 已上传的字节
        // e.total 需要传输的总字节
        let procentComplete = Math.ceil((e.loaded / e.total) * 100);
        console.log(procentComplete);
    }
}
  • HTTP协议
  1. 客户端与服务器之间要实现网页内容的传输,则通信双方必须遵守网页内容的传输协议。网页内容又叫做超文本,因此网页内容的传输协议又叫做超文本传输协议(HyperText Transfer Protocol),即HTTP。

  2. 客户端发起的请求叫做HTTP请求。客户端发送到服务器的消息,叫做HTTP请求消息(HTTP请求报文)。

  3. HTTP请求消息由请求行(request line)、请求头(header)、空行请求体4个部分组成。

image.png

注意,请求体中存放的是通过POST方式提交到服务器的数据,因此只有POST请求才有请求体,GET请求是没有请求体的。

  1. HTTP的请求方法有以下九种,主要的方法是增删改查

image.png

  1. HTTP的响应状态码

image.png

2** 范围的状态码表示服务器已经成功接收到了请求并进行了处理

image.png

4** 范围的状态码表示客户端的请求有非法内容,从而导致这次请求失败

image.png

  • 同源
  1. 什么是同源 如果两个页面的协议域名端口都相同,则两个页面具有相同的源。
    例如http://www.juejin.cn:80/editor.htmlhttps://www.juejin.cn:80/Citizen7.html是两个同源的页面。

  2. 同源策略 同源策略是浏览器提供的一个安全功能。浏览器规定,A网站的JavaScript,不允许和非同源的网站B之间进行资源的交互。

  • 跨域
  1. 什么是跨域 如果两个页面的协议域名端口中任何一个不一样,就叫做跨域。

  2. 浏览器对跨域请求的拦截 由于浏览器同源策略的存在,所以浏览器只允许发起跨域请求,但是跨域请求回来的数据会被浏览器拦截,无法被页面获取到。但是<script>标签不受浏览器同源策略的影响,可以通过src属性,请求非同源的JS脚本。

image.png

  1. 跨域问题的解决 现如今实现跨域数据的请求,主要有两种解决方案,分别是JSONPCORS

JSONP:是前端程序员为了解决跨域问题,被迫想出来的一种临时解决方案。仅支持GET请求,但对浏览器的兼容性较好。
CORS:是W3C用于解决跨域AJAX请求的标准解决方案。支持GET和POST请求,但对某些低版本的浏览器不兼容。

  • JSONP JSONP(JSON with Padding)是JSON的一种使用模式,可用于解决主流浏览器的跨域数据访问问题。由于<script>标签不受浏览器同源策略的影响,所以我们可以通过<script>标签的src属性来请求跨域的数据接口,并通过函数调用的形式接收跨域接口响应回来的数据,这就是JSONP的实现原理。

  • 防抖 防抖策略(debounce)是当事件被触发后,延迟n秒后再执行回调,如果在这n秒内事件又被触发,则重新计时。

image.png

防抖策略可以让一个事件不会被频繁触发,而是在一段时间内只触发一次,因此提高了效率。

比如说我们在输入框输入一串字符,如果没有防抖策略,那么我们每输入一个字符就会搜索一次,这显然没有必要。如果利用防抖策略,那么只有当这一串字符都输入完了才进行一次搜索,显然减少了请求次数。

  • 节流 节流策略(throttle)可以减少一段时间内事件被触发的频率,防止事件无限制地被触发,提高了效率。

image.png

比如当我们连续用鼠标触发一个点击事件时,通过节流策略,让这些点击事件在规定的一段时间内只被实际触发一次。