面试还不会 Ajax?拿来把你

面试还不会 Ajax?拿来把你

CSDN 的感叹号也是标题党文字????

Ajax(Asynchronous Javascript And XML)

最近想着去找个面试,然后看到 Ajax 也是考点之内(面向关键字面试),虽然已经用了很久的 axios 但没有系统的学过 Ajax,所以就有今天这篇文章。

背景介绍

AJAX 全称(Async Javascript and XML)

即异步的 JavaScript 和 XML,是一种创建交互式网页应用的网页开发技术,可以在不重新加载整个网页的情况下,与服务器交换数据,并且更新部分网页

为什么需要 Ajax?如果你用过 JSP 就知道,在 jsp 中你需要返回数据或者需要和服务器交互的时候是要刷新页面的,比如一个主页,你只是需要加载某个 tab 的数据,比如衣物栏

1.png

你可能要付出加载整个页面其他元素的代价,像搜索框对应的 jsp 文件,或者其它的,都要重新传。

现在你很难想象你进入到一个购物商城页面之后,本来主页已经很耗费时间了,然后随便点击某个商品很有可能会花费和进入主页相同的时间,用户不会等待这么久。

对于前端开发来说,jsp 的效率也不是很高,就以我不久前被裹挟着开发了一次 jsp 网上购物商城为例,HTML 是后端返回的,即使在 Chrome 修改了样式文件,仍然需要重启后端(重开 SpringBoot 的时间要很久)你才能够真正看到实际环境下的 HTML 页面,也就是没有热更新;每一次的路由跳转也需要重新加载页面,等待时间大于开发时间。

说了这么多的 jsp 还是回归正题 ajax,ajax 就解决了上面这些缺点,局部更新,减少了用户的等待时间,不必每一次与服务器的交互都要重新加载,无刷新获取数据

实现

Ajax 的原理简单来说通过 XMLHttpRequest 对象来向服务器发异步请求,从服务器获得数据,然后用 JavaScript 来操作 DOM 而更新页面

IMG

请求/响应

XMLHttpRequest

过程是

  • 创建 new XMLHttpRequest
  • 建立连接 open
  • 发送请求 send
  • 回调 onreadystatechange

简单介绍一下 XMLHttpRequest 的上面的这些 API

// 1
const xhr = new XMLHttpRequest();
// 2
xhr.open(method, url, [async][, user][, password])
// 3
xhr.send([body])
// 4
xhr.onreadystatechange = function () {...}

下面是一个 JS 使用 XMLHttpRequest 对象发送请求的一个简单例子

如果你不会本地起个接口,可以去百度一个测试接口网站

//1. 创建对象
const xhr = new XMLHttpRequest();
//2. 初始化 设置请求方法和 url
xhr.open("GET", "http://127.0.0.1:8000/server?a=100&b=200&c=300");
//3. 发送
xhr.send();
//4. 事件绑定 处理服务端返回的结果
// on  当....时候
// readystate 是 xhr 对象中的属性, 表示状态 0 1 2 3 4
// change  改变
xhr.onreadystatechange = function () {
  //判断 (服务端返回了所有的结果)
  if (xhr.readyState === 4) {
    //判断响应状态码 200  404  403 401 500
    // 2xx 成功
    if (xhr.status >= 200 && xhr.status < 300) {
      //处理结果  行 头 空行 体
      //响应
      // console.log(xhr.status);//状态码
      // console.log(xhr.statusText);//状态字符串
      // console.log(xhr.getAllResponseHeaders());//所有响应头
      // console.log(xhr.response);//响应体
    } else {
    }
  }
};

fetch

fetch 据说是以后会替代 ajax 的东西,但现在比较常用的库 axios 并不是基于 fetch 的,但也算比较重要吧?抄一段尚硅谷的代码做示例,感兴趣的可以去看一下 MDN 关于 fetch 的文档

fetch("http://127.0.0.1:8000/fetch-server?vip=10", {
  //请求方法
  method: "POST",
  //请求头
  headers: {
    name: "atguigu",
  },
  //请求体
  body: "username=admin&password=admin",
})
  .then((response) => {
    // return response.text();
    return response.json();
  })
  .then((response) => {
    console.log(response);
  });

超时/重复请求

上面的都是简单的使用,面试也不会让你手撕一个 XMLHttpRequest 请求吧?,所以接下来就讲一下 Ajax 需要注意的几个点。

这里为什么要将超时和重复请求放在一起,因为面向用户来说重复请求大多是因为超时,当然超时和重复请求的场景和原因可能有很多种。

如何处理超时?

XMLHttpRequest 本身就提供了超时相关的 API,使用 timeout 已经 ontimeOut() 可以面临超时的问题,如何在实践中测试超时可以使用 chrome 的控制台,具体可以看这篇文章,chrome 中几种网络限制解释和网络控制,引流-chrome 怎么控制网速

const xhr = new XMLHttpRequest();
xhr.timeout = 2000;
//超时回调
xhr.ontimeout = function () {
  alert("网络异常, 请稍后重试!!");
};

如何处理重复请求?

解决重复请求的意义,减小服务器的压力,因为现在后端的代码可能需要做大量的计算,或者一些数据库操作,所以一次请求可能有 1 - 3 秒,或者因为服务器太拉,对于用户来说 1s 都等不了,发现有长时间的置空状态可能会多次重复操作,比如点击购买按钮,发现没跳转到支付界面,这个时候可能就会再点一次,第二次还没有就第三次。。。。

当然也可以避免多次相同的请求返回多次响应的问题,频繁的弹出响应弹窗,也可以避免后端数据混乱,有很多网站没有做重复请求处理,导致返回相同的数据,比如下拉刷新两次返回两次刷新内容

抢购案例也是重复请求需要解决的问题,用户会多次点击购买按钮,前端需要判断请求是否完成

具体操作如下

// 当然是用一个信号量了
// 老 PV 操作了
let xhr = null;
let isSending = false; // 是否正在发送AJAX请求
...
// 如果正在发送, 则取消该请求, 创建一个新的请求
// abort() 是 xhr 取消请求的方法
if (isSending) xhr.abort();
xhr = new XMLHttpRequest();
//修改标识变量的值
isSending = true;
xhr.open("GET", "http://127.0.0.1:8000/delay");
xhr.send();
xhr.onreadystatechange = function () {
  if (xhr.readyState === 4) {
    //修改标识变量
    isSending = false;
  }
};

IE 缓存

基本不需要关注,了解即可

我也没有去验证过,缓存其实很重要,但这里的缓存针对的是 IE,对于图片等静态资源,但如果普通的 JSON 也缓存的话就会出现问题

跨域

这个老重要,我经常碰到,我碰到的跨域场景可以总结如下

  1. 第一次搭建后端,不会配置
  2. 不熟悉的语言有不同的配置跨域,又得百度
  3. 需要携带 Cookie

具体解决方法可以看一下思否的一个答案,具体是下面的方法

  1. jsonp,只支持 GET 请求
  2. CORS,这个是后端帮助你配置,这种跨域问题最好是交给后端,毕竟没有学习成本,自己一把梭的项目可以考虑
  3. webpack proxy + nginx

还有其他的解决方法,比如在修改你的 Chrome 让它可以跨域,不过对于面试可能不太会问这种

请求/响应扩展

前端开发中不一定都是 get/post 请求,现在后端还有一些其他请求,比如 put/delete/patch,这是偶然看到的某个面试题,其实这涉及到了 RESTful 架构,具体可以去阮一峰老师的博客去了解一下 理解 RESTful 架构,但作者本人从很多网站上看到的更多是 POST 请求一把梭。

注意:XMLHttpRequest 支持上述所有 HTTP 请求方法,一共是 9 种

  1. GET
  2. HEAD
  3. POST
  4. PUT
  5. DELETE
  6. CONNECT
  7. OPTIONS
  8. TRACE
  9. PATCH

封装

因为 XMLHttpRequest 写的是比较麻烦的,所以有一些库对它做了封装,比如 Jquery、axios,Jquery 用的比较少就不讲了,而 axios 它是一个比较新的库,它是基于 XMLHttpRequest 对象的封装。

为什么不使用 fetch,我简单的查了一下看到有人说是 browser and node.js 通用,当然还有更多的比较和考虑,有兴趣的可以参考 https://github.com/axios/axios/issues/3899

它对 XMLHttpRequest 的封装还是有点东西的,下面的面试题也提到了它,会具体的讲一下它的功能和优势。

面试题

我直接上面试题

  • ajax 原理是什么?如何实现?同类型(请详细描述 AJAX 的工作原理)

    原理可以上面已经讲的很清楚了,可以回去再阅读一下
  • ajax 请求地址只支持 http/https 吗?能做到让它支持 rtmp://等其它自定义协议吗 ?

    ajax 只支持 http/https 协议,可以通过自定义 http 头来间接支持自定义协议,我找半天也没有找到类似案例,太难了,PASS 掉
  • 说说防止重复发送 ajax 请求的方法有哪些?各自有什么优缺点?

    1. 防抖 2. 节流 3. 加锁,上面的 ajax 中有讲过加锁的方法,而对于防抖和节流应该是针对短时间内大量调用 ajax 方法的事件处理比较好,比如连续点击抢购按钮的点击事件可以使用防抖节流,不过考虑到绝大多数按钮绑定的点击事件其实也就是一个请求,所以直接在 ajax 上用也是一样的
  • ajax 如何接收后台传来的图片?
    这题考察的是 XMLHttpRequest.response 的返回类型,可以是 ArrayBuffer、Blob、Document,或 DOMString,如果是图片,将 Blob 转换一下就可以变成页面可以展示的图片(百度有很多案例),所以答案是 1.设置 responseType 为 Blob,2.将 Blob 保存为文件

参考文献

【尚硅谷】3 小时 Ajax 入门到精通

ajax 面试提来源 - github haizlin/fe-interview

面试官:ajax 原理是什么?如何实现?

MDN - fetch

阮一峰 - 理解 RESTful 架构

MDN - XMLHttpRequest

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值