主题
Promise 与案例
本页对应 1-8Promise及案例,共 4 段视频,约 38 分钟。
学习目标
- 能用自己的话说明 Promise 是浏览器内置对象,并描述其用于管理异步操作、获取成功或失败结果的作用。
- 能按“实例化 Promise → 在回调中执行异步操作并调用 resolve/reject → 用 then/catch 接收结果”的步骤独立写出可运行代码。
- 能准确说出 Promise 的 pending、fulfilled、rejected 三种状态及其触发条件,并验证状态改变后不可再次改变。
- 能使用 Promise 封装 XHR 请求省份列表,在 then 中接收并渲染数据到页面。
- 能通过 XHR 的 status 判断 2xx 为成功、非 2xx 为失败,并使用 reject(new Error(...)) 传递异常信息。
- 能在 catch 中接收异常对象,通过 console.dir 查看 message 属性并将错误信息渲染到页面。
知识点
Promise 是什么:把异步结果装进对象
为什么需要: 定时器、XHR 请求这类异步操作,结果不会立刻返回。如果只靠回调,成功和失败的处理容易散落在各处。Promise 用来表示一个异步操作的最终完成(或失败)及其结果值,本质是“管理异步操作的对象”。
怎么想: 先别把 Promise 想复杂。它就是一个对象:内部执行异步任务,任务结束后用 resolve 表示成功、用 reject 表示失败;外部用 .then 接成功结果,用 .catch 接失败结果。转写稿里反复强调的 resolve、reject 都是函数参数,不是普通变量。
怎么做: 先实例化:
js
// 1. 实例化Promise对象
const p = new Promise((resolve,reject)=>{
})易错点: new Promise 传入的回调函数会立即执行,所以异步逻辑要写在回调里面;resolve、reject 是函数,调用时才能把结果传出去;Promise 不是“自动等待”的语法,它只是管理异步状态和结果。
为什么学 Promise:逻辑清晰,也能看懂 axios
为什么需要: Promise 让成功或失败关联到后续处理函数,逻辑更清晰;同时,axios 内部就是基于 Promise 封装而成的,学会 Promise 才能更好理解 axios 的 .then、.catch 为什么这样用。笔记还提到,Promise 能解决回调函数地狱问题,后面会展开,今天先掌握基础使用。
怎么想: 转写稿里说,axios 通过 .then 拿成功结果、.catch 拿失败结果,这和 Promise 的用法一致;而“小黄人”指的是 XMLHttpRequest,是底层请求对象。先学会 Promise 管异步任务,再看 axios 就不会只停留在“会调用”。

怎么做: 把 Promise 的三步记牢:实例化、执行异步并传递结果、获取结果。后面写 axios 时,重点观察它的返回值为什么能 .then、.catch。
易错点: 不要把 .then 当成“一定会成功”,也不要把 .catch 只理解成“代码报错”;这里的失败是 Promise 被 reject 后的失败结果。
Promise 的基本使用三步
为什么需要: 异步任务需要固定套路:谁执行、结果怎么传、外面怎么接。Promise 把这三件事拆清楚。
怎么想: 按转写稿的推导:第一步 new Promise,回调里接收 resolve、reject;第二步在回调里执行异步操作,成功调 resolve(成功结果),失败调 reject(失败结果);第三步用 p.then 接成功,用 p.catch 接失败。
怎么做: 笔记中的核心语法如下:
js
// 1. 实例化Promise对象
const p = new Promise((resolve,reject)=>{
// 2. 执行异步操作,并传递结果
// 成功resolve(成功结果) then()执行
// 失败reject(失败结果) catch()执行
})
// 3. 接收结果
p.then(res=>{
// 成功
}).catch(err=>{
// 失败
})
按转写稿的调试过程,可以先用定时器模拟异步:
js
const p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('成功了')
}, 1000)
})
p.then(res => {
console.log(res) // 成功了
}).catch(err => {
console.log(err)
})把 resolve('成功了') 换成 reject('失败了'),成功回调不执行,.catch 里会收到“失败了”。
易错点: 一次异步任务通常只调用 resolve 或 reject 中的一个;结果要通过参数传出去,不能只在回调里 console.log;.then 和 .catch 要写在 Promise 对象外面接收结果。
调试时看状态:先 resolve 后 reject 为什么不生效
为什么需要: 知道状态变化,才能理解 .then、.catch 什么时候触发。转写稿中通过控制台查看 PromiseState:实例化后默认是 pending(待定);调用 resolve 后变成 fulfilled(已兑现),触发 .then;调用 reject 后变成 rejected(已拒绝),触发 .catch。
怎么想: resolve、reject 的本质是改变 Promise 状态,状态改变后才会执行对应处理函数。
怎么做: 在浏览器控制台输入 Promise 变量,展开查看 PromiseState。转写稿还测试了:先 reject 再 resolve,最终仍是 rejected,后面的 resolve 不会再把结果传出去。
易错点: Promise 状态一旦从 pending 变成 fulfilled 或 rejected,就不能再改变;不要在一个 Promise 里既想成功又想失败都生效。
小结检查
- Promise 是什么?表示(管理)一个异步操作最终状态和结果值的对象。
- 为什么学?成功和失败状态可以关联对应处理函数,也能了解 axios 内部运作原理。
- 使用步骤?
new Promise执行异步任务;用resolve关联.then传递成功结果;用reject关联.catch传递失败结果。
课件图示

本节目标与为什么要认识 Promise 的状态
这一节的目标是:认识 Promise 的三种状态,并知道状态改变后如何关联成功/失败的处理函数。
为什么要了解状态?因为 Promise 不是“凭空调用 then 和 catch”的。上一节我们写 resolve()、reject() 时,本质上是在改变 Promise 对象的状态;状态一变,才会触发对应的处理函数。搞清楚状态,才能理解 then 和 catch 什么时候执行、代码按什么顺序走。
可以这样想:把 Promise 看成一个“任务状态机”。任务开始时是待定;任务成功后变成已兑现;任务失败后变成已拒绝。then 关联成功,catch 关联失败。怎么做?先记住三种状态,再用代码观察状态变化。
三种状态:pending、fulfilled、rejected
每个 Promise 对象必定处于以下三种状态之一:
- 待定(pending):初始状态,既没有被兑现,也没有被拒绝。
- 已兑现(fulfilled):操作成功完成。
- 已拒绝(rejected):操作失败。
这里的英文字符串可以理解为 Promise 对象内部的字符串标识符,用来判断什么时候调用哪一个处理函数。注意 PPT 里出现的 fullfilled 是拼写误差,标准写法是 fulfilled。
怎么想?实例化 new Promise() 后,默认就是 pending;调用 resolve() 后变成 fulfilled;调用 reject() 后变成 rejected。
怎么做?可以在浏览器控制台输入 Promise 变量名,展开后查看 PromiseState。转写稿的调试过程是:先实例化但不写异步结果,控制台查看是 pending;调用 resolve 后查看变成 fulfilled;调用 reject 后查看变成 rejected。
易错点:状态不是结果值。resolve('成功了') 中,fulfilled 是状态,'成功了' 是传递出去的结果值,后面会进入 then 回调的参数。
状态如何关联 then 和 catch

这张图要表达的是:Promise 状态改变后,会关联到不同的处理函数。
pending:待定,初始状态,既没成功也没失败。- 调用
resolve():状态从pending变为fulfilled,触发.then(回调函数)。 - 调用
reject():状态从pending变为rejected,触发.catch(回调函数)。
为什么需要这样设计?因为异步操作的结果只有两类:成功或失败。Promise 用状态来区分,外部就用 then 和 catch 分别接收。
怎么想?可以记对应关系:resolve → then,reject → catch。怎么做?在 Promise 回调里调用 resolve 或 reject,外部用 then 或 catch 接收结果。
易错点:不要写成 p.then 处理失败、p.catch 处理成功。转写稿反复强调:成功走 then,失败走 catch。
用代码观察状态变化
先看成功情况:
js
const p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('成功了')
}, 1000)
})
p.then(res => {
console.log(res) // 成功了
})执行过程:实例化时,Promise 回调立刻执行,里面写了定时器;1 秒后调用 resolve('成功了'),状态从 pending 变成 fulfilled,于是 then 的回调执行,res 接收到 '成功了'。在控制台查看 p,展开 PromiseState 可看到 fulfilled。
失败情况:
js
const p = new Promise((resolve, reject) => {
setTimeout(() => {
reject('失败了')
}, 1000)
})
p.catch(err => {
console.log(err) // 失败了
})1 秒后调用 reject('失败了'),状态从 pending 变成 rejected,触发 catch,err 接收到失败结果。控制台查看状态为 rejected。
易错点:then/catch 的回调不是实例化时立刻执行,而是等状态改变后触发;Promise 回调本身是实例化时立刻执行的。
状态敲定后不可逆:调试与易错点
笔记特别提醒:每个 Promise 对象一旦被兑现/拒绝,那就是已敲定了,状态无法再被改变。
转写稿的验证过程是:先调用 reject,状态变成 rejected;后面再调用 resolve,发现 then 没有输出,控制台查看状态仍然是 rejected。反过来先 resolve 再 reject,状态也会固定在 fulfilled。
js
const p = new Promise((resolve, reject) => {
resolve('第一次成功')
reject('再失败')
})
p.then(res => {
console.log(res) // 第一次成功
})
p.catch(err => {
console.log(err) // 不会执行
})怎么想?状态只能从 pending 转向 fulfilled 或 rejected 一次,之后不可逆。怎么做?调试时在控制台输入变量名,展开看 PromiseState,不要只看有没有打印。易错点:不要以为后写的 reject 会覆盖前面的 resolve;也不要在 pending 阶段就期待 then/catch 执行。
小结与自测
Promise 对象有 3 种状态:待定 pending、已兑现 fulfilled、已拒绝 rejected。状态的作用是:状态改变后,决定关联执行哪个处理函数。成功 resolve 对应 then,失败 reject 对应 catch,且状态一旦敲定不可再改。
保留本节笔记中的小结代码:
html
<details>
<summary>答案</summary>
<ul>
<li>待定 pending,已兑现 fulfilled,已拒绝 rejected</li>
</ul>
</details>
<details>
<summary>答案</summary>
<ul>
<li>状态改变后,如何关联处理函数</li>
</ul>
</details>课件图示

本节目标与整体思路
转写稿里的“小黄人”指 XHR/XMLHttpRequest,“Henice”指 then,“cash”指 catch,本文统一按正确术语书写。本节目标是:用 Promise 管理 XHR 异步任务,请求省份列表并展示到页面;再用错误地址演示 404,补上异常处理。需求来自笔记:核心功能是“Promise + XHR 获取省份数据并渲染”,异常处理是“请求失败时把服务器提示信息渲染到页面”。整体结构就是 PPT 中的三步:请求数据 → 传递数据 → 接收并使用数据。
为什么需要: XHR 本身是回调式异步代码,成功、失败、后续渲染容易散落在事件回调里;Promise 可以把“异步操作”和“结果处理”分开,成功走 then,失败走 catch,结构更清楚。
怎么想: 把 XHR 的异步代码放进 new Promise((resolve, reject) => { ... }) 的执行器里;XHR 成功时调用 resolve(数据),失败时调用 reject(错误);外部用 p.then(...).catch(...) 接收。
怎么做: 先写 Promise 外壳,再在内部创建 XHR、open、监听 loadend、send,最后在 then 中渲染。
易错点: 不要忘记 send();不要在 XHR 还没回来时提前 resolve;Promise 状态从 pending 变成 fulfilled 或 rejected 后不可逆,调用 resolve 后再调用 reject 不会再次改变状态。
核心功能:Promise + XHR 获取省份列表
为什么需要: 省份列表来自服务器,必须发 AJAX 请求;用 Promise 管理后,后续渲染逻辑可以集中写在 then 中。
怎么想: XHR 的 loadend 在响应回来后执行,此时能拿到 xhr.response;接口返回的是 JSON 字符串,先 JSON.parse 转成 JS 对象,再 resolve 出去;外部 then 里拿到对象,取 res.list 渲染到 .box。
怎么做: 代码可写成下面的结构。注意接口地址用占位,不编造具体域名;演示异常时再把地址改错,例如在末尾加 123。
js
const p = new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('GET', '省份列表接口地址');
xhr.addEventListener('loadend', () => {
// 先判断响应状态码,成功范围是 200~299
if (xhr.status >= 200 && xhr.status < 300) {
// xhr.response 是 JSON 字符串,转成 JS 对象后传递
resolve(JSON.parse(xhr.response));
} else {
// 失败时把服务器返回的信息包装成错误对象
reject(new Error(xhr.response));
}
});
xhr.send();
});
p.then(res => {
// 核心功能:把省份列表渲染到页面
document.querySelector('.box').innerText = res.list;
}).catch(err => {
// 异常处理:把错误信息渲染到页面
document.querySelector('.box').innerHTML = err.message;
});调试时可以按转写稿的过程理解:先在 loadend 里打印 xhr.status,看到 200,说明请求成功;再打印 xhr.response,确认它是 JSON 字符串;JSON.parse 后在 then 中打印 res,点开后找到 list 属性;最后用 document.querySelector('.box') 拿到盒子,把 res.list 放进去。核心功能中渲染列表用 innerText,因为这里只是展示数据,不解析标签。
易错点: xhr.status 才是响应状态码,不要写成 xhr.state;JSON.parse 只应在成功分支里做;失败时 xhr.response 可能是错误提示文本甚至 HTML 片段,不要盲目 parse;忘记 xhr.send() 会导致请求根本没发出。
异常处理:用状态码判断成功或失败
为什么需要: 只写 then 只能处理成功;请求地址错误、服务器返回 404 时,必须让 Promise 进入 rejected 状态,外部 catch 才能拿到异常并渲染提示。
怎么想: AJAX 判断成功不是看“有没有报错”,而是看响应状态码:xhr.status >= 200 && xhr.status < 300 为成功;不在这个范围就是失败。失败时调用 reject,并把服务器返回的信息用 new Error(...) 包装,外部 catch 的参数 err 就能通过 err.message 取到提示。
怎么做: 在 loadend 中写 if/else;成功 resolve(JSON.parse(xhr.response)),失败 reject(new Error(xhr.response));外部 .catch(err => { document.querySelector('.box').innerHTML = err.message; })。异常信息来自服务器,可能是带标签的提示,所以这里用 innerHTML 渲染。调试时把地址改错,看到状态码从 200 变成 404;打印 xhr.response 能看到服务器返回的“找不到”提示;如果直接 console.log(err) 看不到内部属性,可用 console.dir(err) 查看对象,找到 message 属性后再渲染。
易错点: 不要用 xhr.status === 200 写死,因为成功范围是 200 到 299;404 是“找不到”,不是成功;失败分支不要继续 JSON.parse;err 是错误对象,页面要取 err.message,不是直接把整个对象塞进去。
小结:AJAX 如何判断请求响应成功
本节小结的答案是:响应状态码在大于等于 200 并且小于 300 的范围是成功的。对应到 Promise:成功调用 resolve,状态变为 fulfilled,触发 then;失败调用 reject,状态变为 rejected,触发 catch。实例化后的默认状态是 pending,状态一旦改变就不能再改。把这条判断写进 XHR 的 loadend,再用 Promise 串起 then 和 catch,就完成了“获取省份列表 + 异常提示”的完整流程。
课件图示


代码示例
示例 1:Promise 基础用法与三种状态(定时器模拟异步)
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>01-Promise 基础用法与状态</title>
</head>
<body>
<script>
// 第 1 步:实例化 Promise 对象,回调函数接收 resolve / reject 两个函数参数
const p = new Promise((resolve, reject) => {
// 这个回调在实例化时"立刻执行",里面写异步操作
setTimeout(() => {
// 第 2 步:异步成功 -> 调用 resolve,状态 pending 变成 fulfilled,结果传给 then
resolve('成功了,很开心');
// 异步失败 -> 调用 reject,状态 pending 变成 rejected,结果传给 catch
// reject('嘤嘤嘤失败了');
}, 1000);
});
// 第 3 步:then 接收成功结果(对应 resolve),catch 接收失败结果(对应 reject)
p.then((res) => {
console.log('then 拿到成功结果:', res);
}).catch((err) => {
console.log('catch 拿到失败结果:', err);
});
// 状态验证:实例化后同步打印,此时还是 pending(待定)
console.log('同步打印状态(pending):', p);
setTimeout(() => {
console.log('1 秒后状态:', p); // fulfilled(已兑现)或 rejected(已拒绝)
}, 1500);
// 状态一旦敲定就不可再改变:先 reject 再 resolve,resolve 无效
const p2 = new Promise((resolve, reject) => {
reject('第一次就失败了'); // 状态敲定为 rejected
resolve('我又成功了'); // 不会生效,状态无法再改变
});
p2.then((res) => console.log('p2-then:', res))
.catch((err) => console.log('p2-catch:', err));
setTimeout(() => console.log('p2 最终状态:', p2), 100);
</script>
</body>
</html>关键行与易错点
new Promise((resolve, reject) => {...}):回调里的代码在实例化时立刻执行,不是等then才执行;resolve/reject是浏览器传进来的函数,不是自己定义的。- 对应关系不能记反:
resolve(成功)→then;reject(失败)→catch。这和 axios 的.then/.catch是同一套机制。 - 三种状态:
pending(待定,实例化后的默认值)→fulfilled(已兑现,调resolve时)/rejected(已拒绝,调reject时)。 - 易错点:状态一旦改变就敲定,不可逆。先调
reject再调resolve,后者不生效,then也不会执行;控制台展开 Promise 对象即可看到PromiseState。 - 易错点:
console.log(p)在同步代码里看到的是pending,想看结果状态要放进定时器/回调里再打印。
示例 2:Promise + XHR 获取省份列表(核心功能)
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>02-Promise + XHR 获取省份列表</title>
</head>
<body>
<div class="box"></div>
<script>
// 1. 创建 Promise 对象,用 Promise 管理 XHR 异步任务
const p = new Promise((resolve, reject) => {
// 1.1 请求数据:XHR 代码写在回调函数里,实例化时就会发请求
const xhr = new XMLHttpRequest();
xhr.open('GET', 'https://hmajax.itheima.net/api/province'); // 换成你课程资料里的省份列表接口地址
xhr.addEventListener('loadend', () => {
// response 是 JSON 字符串,先转成 JS 对象再往外传,外部就不用再转
const data = JSON.parse(xhr.response);
// 1.2 传递数据:成功调用 resolve
resolve(data);
});
xhr.send();
});
// 2. 接收并使用数据:resolve 后状态变成 fulfilled,触发 then 的回调
p.then((res) => {
console.log('接收到的数据:', res); // 打印出来是个对象,要的是 res.list
document.querySelector('.box').innerHTML = res.list;
});
</script>
</body>
</html>关键行与易错点
- XHR 的三件套顺序不能乱:
open→ 注册loadend事件 →send();忘了xhr.send()请求根本不会发出去,这是最常见的漏写。 - 数据必须在
loadend事件里取,用xhr.response;此时拿到的是 JSON 字符串,所以用JSON.parse转成对象后再resolve,让外部直接可用。 - 易错点:把 XHR 代码写在
new Promise回调外面。写在回调里,才能用resolve把结果“抛”给then。 res.list是数组,直接赋给innerHTML会按逗号拼接显示;想换行可以res.list.join('<br>')。- 接口地址请以你课程接口文档中的省份列表接口为准,替换上方 URL 即可。
示例 3:Promise + XHR 异常处理(状态码判断 + reject 传递错误)
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>03-Promise + XHR 异常处理</title>
</head>
<body>
<div class="box"></div>
<script>
const p = new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
// 故意写错地址,演示 404 异常(正确地址去掉 123)
xhr.open('GET', 'https://hmajax.itheima.net/api/province123');
xhr.addEventListener('loadend', () => {
// 2.1 判断请求状态:2xx(200~299)才算成功
if (xhr.status >= 200 && xhr.status < 300) {
const data = JSON.parse(xhr.response);
resolve(data); // 成功:状态 -> fulfilled,触发 then
} else {
// 2.2 传递异常信息:用 Error 对象包一层再 reject
reject(new Error(xhr.response)); // 失败:状态 -> rejected,触发 catch
}
});
xhr.send();
});
p.then((res) => {
document.querySelector('.box').innerHTML = res.list;
}).catch((err) => {
// 2.3 接收并处理异常
console.log('catch 里的 err:', err); // 直接 log 看不到 message 里的内容
console.dir(err); // 以对象形式打印,能看到 message 属性
document.querySelector('.box').innerHTML = err.message;
});
</script>
</body>
</html>关键行与易错点
xhr.status是响应状态码(本次新学的属性):200~299为成功,404是找不到资源。判断条件写成>= 200 && < 300,不要写成=== 200,也不要写成<= 300。- 易错点:
JSON.parse只能放在成功分支里。404 时xhr.response返回的是一段 HTML 错误提示,直接 parse 会抛语法错误。 reject(new Error(xhr.response)):传的是 Error 对象而不是裸字符串,这样catch里才能用err.message取到文本。- 易错点:
console.log(err)看到的是Error对象本身,属性内容要展开或改用console.dir(err)才能看到message。 - 渲染错误提示用
innerHTML赋err.message(纯文本);若赋整段xhr.response会连 HTML 标签一起渲染进盒子。
常见错误
1. 在 Promise 回调外调用 resolve/reject
- 现象:控制台报
resolve is not defined,或异步结果永远拿不到,then里的回调不执行。 - 原因:
resolve/reject是new Promise((resolve, reject) => {...})回调函数的形参,只在回调函数作用域内有效;写到外面或忘记声明形参都用不了。 - 修法:确认构造函数内的回调形参写成
(resolve, reject),并把resolve(...)/reject(...)的调用写在回调函数体内(通常位于定时器、XHR 的回调里)。
2. 状态改变后再次调用 resolve/reject,误以为还能切换成功/失败
- 现象:先调用
reject再调用resolve,then的回调始终不执行,Promise 状态仍是rejected。 - 原因:Promise 状态一旦从
pending变为fulfilled或rejected就不可逆,后续调用被忽略。 - 修法:把成功/失败判断集中在一次
resolve/reject调用上(如用if (xhr.status >= 200 && xhr.status < 300)二选一分支),不要指望“后写覆盖先写”。
3. 只写 then 不写 catch,异常信息拿不到
- 现象:请求地址写错时页面无任何提示,控制台可能只有 XHR 的红色报错,自己的失败处理逻辑没跑。
- 原因:
reject传递的失败结果只能被catch(或then的第二个参数)接收,只写then时失败分支无人处理。 - 修法:链式补上
.catch(err => {...});并在 XHR 的loadend里按状态码判断,失败时reject(new Error(xhr.response))。
4. 用 console.log 打印 Error 对象,看不到 message
- 现象:
console.log(err)输出一个 Error 对象,展开后找不到想渲染的提示文本。 - 原因:
console.log对 Error 对象的展示不展开自有属性,需换用能展开对象的输出方式。 - 修法:改用
console.dir(err)查看message属性,页面渲染时直接取err.message而不是整个err。
5. 状态码判断写成 === 200,把其他成功响应当失败
- 现象:接口返回 201/204 时走进
catch分支,页面显示异常信息。 - 原因:HTTP 成功是 200–299 的区间,不是单一值。
- 修法:写成
xhr.status >= 200 && xhr.status < 300,或用xhr.status >= 200 && xhr.status <= 299。
6. 在 XHR 回调里直接 return 数据,而不调用 resolve
- 现象:
then里拿到的是undefined。 - 原因:
return只结束当前回调函数,不会把值交给 Promise;只有resolve(值)才会把结果传给then。 - 修法:在
loadend中resolve(JSON.parse(xhr.response)),把解析后的数据作为成功结果传出。
练习
1. 定时器版 Promise 基础 用 new Promise 包装一个 1 秒定时器,成功时传出字符串“任务完成”,失败时传出“任务失败”;外部用 then/catch 分别打印。要求:先测成功,再注释掉 resolve 测失败。
2. 状态观察实验 实例化一个只写了 setTimeout 的 Promise(不调用 resolve/reject),在浏览器控制台打印该对象并查看 PromiseState;然后在定时器里分别调用 resolve、reject,再各看一次状态值,记录三次结果。
3. 不可逆验证 写一个 Promise:定时器里先 resolve('A'),紧接着再 reject('B')。观察 then 与 catch 哪个执行、控制台打印的状态是什么,并用一句话解释原因。
4. Promise 封装 XHR 获取省份列表 用 new Promise 包裹 XMLHttpRequest,请求省份列表接口,成功时 resolve(JSON.parse(xhr.response).list),失败时 reject(new Error(xhr.response));外部 then 中把数组渲染到 .box 容器,catch 中把 err.message 渲染到同一容器。
5. 异常分支改造 把第 4 题中的地址故意改错(如末尾加 123),要求:在 loadend 里先打印 xhr.status,用状态码区间判断走 resolve 还是 reject,并在 catch 里分别用 console.log(err) 和 console.dir(err) 对比输出差异。
原视频对照
| # | 视频 | 时长 |
|---|---|---|
| 1 | 认识-Promise | 08:16 |
| 2 | 了解-Promise的状态 | 09:53 |
| 3 | 案例-使用Promise加XHR获取省份列表-核心功能 | 09:12 |
| 4 | 案例-使用Promise加XHR获取省份列表-异常处理 | 10:44 |
小结
- Promise 是浏览器内置对象,用来管理异步操作的最终状态与结果值,
then接成功、catch接失败,与 axios 的用法一脉相承。 - 使用固定三步:
new Promise((resolve, reject) => {...})实例化 → 在回调内执行异步任务并用resolve/reject传出结果 → 外部.then()/.catch()接收处理。 - 三种状态
pending/fulfilled/rejected与代码一一对应:实例化即pending,调用resolve转fulfilled,调用reject转rejected。 - 状态改变是触发回调的唯一开关:状态不变则
then/catch都不会执行;状态一旦敲定就不可逆,重复调用被忽略。 - 用 Promise 管理 XHR 时,XHR 代码写在构造函数回调内,
resolve/reject写在loadend里,send()不能漏。 - 判断请求成功用状态码区间 200–299,而不是等于 200;失败时用
reject(new Error(xhr.response))包装成错误对象传出。 - 调试 Error 对象用
console.dir看message属性,页面渲染时取err.message而非整个对象。 - 把定时器换成 XHR 后,
resolve/reject的传递逻辑完全不变——这正是 Promise 能统一管理各类异步任务的体现。