关于Ajax...
尝试把以前一些很晕的概念连起来…
什么是AJAX?
- AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。
- AJAX是一种在Web应用中通过异步发送HTTP请求向服务器获取内容,并使用这些新内容更新页面中相关部分,而无需中心加载整个页面的Web开发技术,这可以让页面更具响应性,因为只请求了需要更新的部分。
- 起初,AJAX通过使用XMLHttpRequest接口实现,但是现在,fetch() API更适合用于开发现代Web应用。
XMLHttpRequest:AJAX的最初实现
- 虽然叫XMLHttpRequest,但是它可以用于请求任何类型的数据,而不仅仅是XML。
- 甚至支持HTTP以外的协议,比如file和ftp。但是可能受到更多出于安全等原因的限制。
1 | // 1. 创建实例化对象 |
- 还有一些其他的属性和方法:
responseText
:返回请求的响应文本responseXML
:返回请求的响应XML文档responseURL
:返回请求的响应URLtimeout
:设置请求的超时时间upload
:返回一个XMLHttpRequestUpload对象,用于表示上传的进度withCredentials
:设置是否携带跨域凭证abort()
:取消请求
Promise:更优雅的异步处理
- 在进入fetch()这个现代化实现AJAX之前,我们先来看看Promise。
- Promise是一种更优雅的异步处理方式,它是一个对象,代表一个异步操作的最终完成或失败以及其结果值。
- fetch正是基于Promise实现的。
如果没有Promise,我们需要在一开始把回调函数作为参数传入函数中,一个回调函数在成功时被调用,另一个则在异常时被调用。
1 | function successCallback(result) { |
但是如果我们重写doSomething()函数,使其返回一个Promise对象,我们就可以使用then()方法来处理成功和失败的情况。
1 | doSomething(settings).then(successCallback, failureCallback); |
那么这种写法有什么好处呢?
链式调用
如果我们需要连续执行两个或者多个异步操作,在上一个操作执行成功之后,开始下一个操作,并带着上一步操作返回的结果,在旧的回调风格中会导致经典的回调地狱。
1 | doSomething(settings, function (result) { |
而在Promise中,我们可以使用then()方法来解决这个问题。因为回调函数是附加到Promise对象上,而不是传入一个函数中的。then()方法返回一个
新的Promise对象。
then的回调函数传入的参数是上一个Promise对象的resolve()方法传入的参数。
如果上一个then的回调函数返回的只是一个普通的值,那么下一个then的回调函数的参数就是这个值。
而then函数返回的是一个新的Promise对象,所以可以继续调用then方法。但是兑现值往往是undefined。
如果上一个处理器启动了一个Promise但是没有返回,那么就没办法再追踪它的敲定状态了,这个Promise就是漂浮的。
一个经验法则是操作每次遇到一个Promise就返回它,并把它的处理推迟到下一个then服务器中
1 | doSomething(settings) |
那么doSomething()函数是如何返回一个Promise对象的呢?
1 | function doSomething(settings) { |
async/await是Promise的语法糖,可以让我们更优雅地处理异步操作。
1 | async function foo() { |
2. 组合
Promise.all
我们可以同时启动所有操作,再等待它们全部完成。
如果数组中的某个Promise被拒绝,Promise.all返回的Promise会立即被拒绝,并终止其他操作。
1 | Promise.all([doSomething(), doSomethingElse(), doThirdThing()]) |
fetch():现代化的AJAX实现
- fetch 是对 XHR 的替代,是浏览器原生支持的基于 Promise 的 HTTP 客户端。
- Window接口的fetch()方法用于发起获取资源的请求,他会返回一个会在请求响应后兑现的promise。
- 该promise会兑现一个表示请求响应的Response对象。
- 当请求失败时,fetch()的promise才会被拒绝。fetch()的promise不会因为服务器响应表示错误的HTTP码(404、500等)
而被拒绝,因此then()处理器必须检查Response.ok或Response.status属性。
1 | fetch('/api/user') |
如果换成我们刚刚提到的async/await,那么代码会更加简洁。
1 | async function foo() { |
Axios:更强大的AJAX库
- Axios 是一个基于 promise 网络请求库,作用于node.js 和浏览器中。 它是 isomorphic 的(即同一套代码可以运行在浏览器和node.js中)。在服务端它使用原生 node.js http 模块, 而在客户端 (浏览端) 则使用 XMLHttpRequests。
- 特点:
- 支持Promise API
- 请求和响应拦截器
- 转换请求和响应数据
- 取消请求
- 自动转换JSON数据
- 客户端支持防止CSRF(跨站请求伪造)
1 | axios.get('/api/user') |
具体的方法还有很多,比如post、put、delete,参照官方文档链接:Axios
拦截器
- axios的一大特点就是拦截器。
- 请求拦截器:在请求被发送之前拦截它们,可以用来修改请求的配置信息。
- 响应拦截器:在响应被 then 或 catch 处理前拦截它们,可以用来修改响应的数据。
1 | // 添加请求拦截器 |
1.❓什么是 AJAX?它的作用是什么?
答:
AJAX 是 Asynchronous JavaScript and XML 的缩写,指的是在网页无需重新加载的情况下,通过 JavaScript 异步发送 HTTP 请求并获取数据,从而局部更新页面内容的一种技术方案。它提升了用户体验,使页面响应更快、交互更自然。
2.XMLHttpRequest 是什么?是不是只能请求 XML?
答:
XMLHttpRequest(XHR)是浏览器早期用于实现 AJAX 的核心 API,尽管名字中包含 XML,但它可以请求任何类型的数据,比如 JSON、HTML、纯文本、图片等。XHR 支持 GET、POST 等 HTTP 请求,具备请求状态管理、取消、设置超时、跨域凭证等功能。
3.Promise 的核心概念是什么?有哪几种状态?
答:
Promise 是 ES6 提供的一种用于管理异步操作的机制。它代表一个将来可能完成或失败的操作及其结果。
Promise 有三种状态:
pending
:初始状态,未完成fulfilled
:操作成功完成rejected
:操作失败
Promise 提供 .then()
和 .catch()
方法来注册成功或失败的回调。
4.Promise 和回调函数的区别?为什么推荐 Promise?
答:
传统异步用回调函数处理,但多层嵌套容易出现“回调地狱”;Promise 通过链式调用 .then()
,让异步流程更清晰、更可控,且支持统一错误处理。Promise 是更现代的异步抽象,结合 async/await
更像同步代码。
5.什么是 then()
的返回值?链式调用是如何实现的?
答:
每个 .then()
方法会返回一个新的 Promise,这个新的 Promise 的状态由 .then()
回调函数的返回值决定。如果返回的是普通值,该值会传给下一个 .then()
;如果返回的是 Promise,则会等待它完成后再传递其结果。
6.什么是 async/await?和 Promise 有什么关系?
答:
async/await
是基于 Promise 的语法糖:
async
用于定义一个异步函数,它返回一个 Promise。await
用于等待一个 Promise 完成,它会暂停当前函数,直到 Promise 完成,并返回结果。
它让异步流程写法更接近同步代码,可读性更强。
7.await Promise.all()
是什么?应用场景是什么?
答:
Promise.all([p1, p2, ...])
会并发执行所有 Promise,只有当全部 Promise 成功时,结果才会返回为一个数组,按顺序对应每个任务结果。若有一个失败,则整个 Promise.all
立即 reject,常用于多个接口并发加载。
8.fetch 和 XMLHttpRequest 有什么区别?
答:
特性 | fetch | XMLHttpRequest |
---|---|---|
是否原生 Promise | ✅ 是 | ❌ 否,需要手动封装 |
是否支持拦截器 | ❌ 不支持 | ❌ 不支持 |
错误处理 | 仅网络错误会 reject | HTTP 错误需手动处理 |
语法简洁 | ✅ 使用更现代语法 | ❌ 写法复杂 |
fetch 是浏览器对 XHR 的现代替代方案,语法基于 Promise,更清晰,但不自动处理 HTTP 错误。
9.axios 是什么?它和 fetch 的区别是什么?
答:
axios 是一个第三方 HTTP 客户端库,在浏览器中基于 XHR,在 Node.js 中基于 http 模块。它封装了很多高级功能,比如:
- 自动 JSON 转换
- 请求和响应拦截器
- 请求超时控制
- 支持取消请求
- 统一错误处理
相比之下,fetch 是浏览器内置 API,更轻量,但功能基础。
10.axios 如何设置请求/响应拦截器?常用场景有哪些?
答:
拦截器是 axios 提供的中间层机制:
1 | axios.interceptors.request.use(config => { |
常见应用:
- 请求前统一添加 token
- 响应后统一剥离结构(只返回 data)
- 错误状态统一弹窗或跳转
11.axios 为什么被称为“HTTP 客户端”?
答:
因为它的职责是“发起 HTTP 请求并处理响应”,这正是客户端行为(请求方)的定义。HTTP 客户端包括:浏览器、Postman、curl、axios。它们不监听端口、不处理传入请求,只是发出请求。
12.axios 和 fetch 都是 XMLHttpRequest 的封装吗?
答:
- fetch:不是封装,而是原生替代(浏览器新内核实现)
- axios:在浏览器中基于 XMLHttpRequest 实现,在 Node 中则用
http
模块
可以认为 axios 是对 XHR 的更高级封装,提供统一接口。
13.fetch 为什么要调用两次 .then()
才能拿到数据?
答:
fetch 第一次 .then()
返回的是 Response
对象,必须调用 response.json()
或 .text()
等方法才能读取真正的数据。因为 response.body
是可读流,要异步解析。
1 | fetch('/api/user') |
14.axios 默认会处理哪些事情?fetch 要手动做什么?
功能 | axios ✅(自动) | fetch ❌(手动) |
---|---|---|
JSON 自动解析 | ✅ res.data |
❌ 要 .json() |
HTTP 错误抛异常 | ✅ 自动进入 catch | ❌ 需手动 res.ok 判断 |
设置请求头 | ✅ 自动设 Content-Type | ❌ 需手动设置 |
请求超时 | ✅ 支持 timeout | ❌ 需自封装 |
请求取消 | ✅ 支持 CancelToken | ✅ 支持 AbortController(较新) |
15.写一个 async 函数调用 axios 请求,并加上错误处理?
答:
1 | async function getUser() { |
16.解释下这段代码的流程:
1 | fetch('/api/user') |
答:
- fetch 发出 HTTP 请求,返回一个
Promise<Response>
- 第一个
.then()
处理响应,将 response.body 解析为 JSON,返回Promise<object>
- 第二个
.then()
拿到 JSON 数据,打印结果