主题
Promise 与案例
本页对应 1-8Promise及案例,共 4 段视频,约 38 分钟。
学习目标
- 能用自己的话说明 Promise 是浏览器内置对象,并描述其管理异步操作、获取成功或失败结果的作用。
- 能独立编写 Promise 三步使用代码:实例化并传入回调函数、在回调中执行异步操作并调用 resolve/reject、通过 then/catch 接收结果。
- 能准确说出 Promise 的 pending、fulfilled、rejected 三种状态及其对应触发条件,并能验证状态一旦改变后不可再次改变。
- 能使用 Promise 管理 XHR 请求省份列表,在异步成功后调用 resolve 传递数据,并通过 then 接收数据完成页面渲染。
- 能通过 XHR 的 status 属性判断请求是否成功,并在失败时使用 reject 传递 Error 对象,通过 catch 接收异常信息并渲染到页面。
知识点
先明确:Promise 到底解决什么问题
为什么需要:异步操作的结果不会立刻拿到,比如定时器、XHR 请求。过去我们容易把“发请求”和“拿到结果后怎么处理”写散,甚至层层嵌套。Promise 的价值是把异步操作“管理”起来,让成功走一条处理链,失败走另一条处理链,逻辑更清楚。
怎么想:笔记给的定义是:Promise 对象用于表示一个异步操作的最终完成(或失败)及其结果值。换句话说:它是一个管理异步操作的对象,不仅能管理过程,还能把成功或失败的结果交给后续函数。还强调,学习 Promise 的另一个原因是理解 axios 内部运作机制——axios 的 .then() 拿成功结果、.catch() 拿失败结果,本质上就建立在 Promise 之上。

怎么做:先记住三个动作:实例化 Promise、执行异步操作并传递结果、用 then/catch 接收结果。
易错点:不要把 Promise 当成“立刻拿到结果”的工具;它管理的是异步结果,结果要通过 resolve/reject 传出去。
Promise 的基本语法与三步使用
为什么需要:只背定义不会用,必须把“异步任务—结果传递—结果接收”串起来。
怎么想:笔记和 PPT 把步骤压成三步:1. 实例化 Promise 对象;2. 执行异步操作,并传递结果;3. 获取结果。成功调用 resolve,对应外部 .then();失败调用 reject,对应外部 .catch()。

怎么做:PPT 中的基础代码结构如下:
js
// 1. 实例化Promise对象
const p = new Promise((resolve,reject)=>{
// 2. 执行异步操作,并传递结果
// 成功resolve(成功结果) then()执行
// 失败reject(失败结果) catch()执行
})
// 3. 接收结果
p.then(res=>{
// 成功
}).catch(err=>{
// 失败
})实际演示中是先用定时器模拟异步:new Promise((resolve, reject) => { setTimeout(() => { resolve('成功了') }, 1000) }),然后写 p.then(res => { console.log(res) })。控制台一秒后打印“成功了”。失败测试则把 resolve 换成 reject('失败了'),外部改用 p.catch(err => { console.log(err) }),就能接收失败结果。
易错点:new Promise() 传入的回调函数会在实例化时立刻执行,所以异步代码要写在这个回调里面;resolve、reject 是函数,不是普通变量;成功和失败只走对应的一条链,不要在外层直接写结果。
顺带确认状态:pending、fulfilled、rejected
为什么需要:知道状态,才能理解为什么调用 resolve/reject 后 then/catch 会执行。
怎么想:调试时在控制台输入变量 p,展开后看 PromiseState。刚实例化时是 pending(待定);调用 resolve 后变成 fulfilled(已兑现);调用 reject 后变成 rejected(已拒绝)。状态改变后,才会触发对应的回调。
怎么做:写成功逻辑后,在控制台查看 p 的状态;写失败逻辑后再查看一次。实际还专门测试了“状态改变后能不能再变”:先 reject,再写 resolve,结果外部没有收到第二次成功结果,状态仍然是 rejected。
易错点:Promise 状态一旦从待定变成已兑现或已拒绝,就“敲定”了,不能再改。不要在一个 Promise 里既想成功又想失败地反复切换。
为什么它和 axios 长得像
为什么需要:很多同学看到 .then()、.catch() 会觉得眼熟,因为 axios 就是这样用的。
怎么想:笔记说,Promise 的好处之一是“了解 axios 函数内部运作的机制”。需要明确:axios 是基于 Promise 和 XHR 封装而成的;then 接收成功结果,catch 接收失败结果。先学 Promise,再自己实现一个简易 hmAxios,就能更好理解 axios 原理。
怎么做:后续案例中,把定时器换成 XHR:在 Promise 回调里创建 XHR、open、监听 loadend,请求成功后用 resolve 传出数据;判断 xhr.status 在 200–299 之间算成功,否则用 reject(new Error(xhr.response)) 传出异常。外部仍然用 .then() 渲染数据,用 .catch() 渲染错误信息。PPT 中给出的调用形态是:
js
hmAxios({
url: 'URL地址',
// method:'get'
}).then(res => {
// 成功
}).catch(err => {
// 失败
})
function hmAxios(config) {
// 略
}易错点:真实请求里要判断响应状态码,不能只看“请求发出去了”;异常信息建议包装成 Error 对象再 reject,外部 catch 里通过 err.message 取信息。
小结:三问要能答上来
- 什么是 Promise? 表示或管理一个异步操作最终状态和结果值的对象。
- 为什么学习 Promise? 成功和失败状态可以关联对应处理函数,也能帮助理解 axios 内部原理。
- 使用步骤? ①
new Promise执行异步任务;② 用resolve关联then的回调传递成功结果;③ 用reject关联catch的回调传递失败结果。
记住对应关系:resolve → then,reject → catch;状态一旦敲定不可逆。
为什么先认识 Promise 的状态
上一节我们已经知道 Promise 的基本用法:实例化 Promise 对象,在回调函数里执行异步操作,成功调用 resolve,失败调用 reject,外部用 .then() 接收成功结果,用 .catch() 接收失败结果。这一节进一步说明:调用 resolve 或 reject 的本质,是改变 Promise 对象的状态;状态改变后,才会触发对应的处理函数。
为什么需要:如果不理解状态,就容易把 .then()、.catch() 当成“随便写的两个回调”,不知道它们为什么执行、什么时候执行。
怎么想:把 Promise 看成一个“管理异步操作的对象”,它内部有一个状态标识;异步操作完成后,通过 resolve / reject 把状态从“待定”改成“成功”或“失败”。
怎么做:先记住基本结构:
js
const p = new Promise((resolve, reject) => {
// 执行异步操作,并传递结果
// 成功:resolve(成功结果) -> then() 执行
// 失败:reject(失败结果) -> catch() 执行
})
p.then(res => {
// 接收成功结果
}).catch(err => {
// 接收失败结果
})易错点:resolve 对应 .then(),reject 对应 .catch();Promise 的回调函数在实例化时会立刻执行,但异步结果要等异步操作完成后再传递出去。
三种状态分别是什么
每个 Promise 对象必定处于以下三种状态之一:
- 待定(pending):初始状态,既没有被兑现,也没有被拒绝。
- 已兑现(fulfilled):操作成功完成。
- 已拒绝(rejected):操作失败。
为什么需要:状态是 Promise 内部判断“该调用哪个处理函数”的依据。
怎么想:状态不是结果值本身。resolve('成功了') 中的 '成功了' 是结果值,状态变成 fulfilled 才是“成功”的标识。
怎么做:调试时先只实例化 Promise,在浏览器控制台输入变量 p 并展开,看到 PromiseState 为 pending;调用 resolve 后再查看,状态变为 fulfilled;调用 reject 后查看,状态变为 rejected。
易错点:fulfilled 不要拼错;pending 是初始状态,不是失败;不要试图手动修改状态字符串,状态应由 resolve / reject 改变。
状态改变后如何关联处理函数

当状态从 pending 变为 fulfilled,会触发 .then() 里的回调;变为 rejected,会触发 .catch() 里的回调。
为什么需要:知道关联关系,才能把成功逻辑写在 .then(),失败逻辑写在 .catch()。
怎么想:resolve 是“成功”,所以对应 then;reject 是“失败”,所以对应 catch。
怎么做:用定时器模拟异步操作,一秒后调用 resolve:
js
const p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('成功了,很开心')
}, 1000)
})
p.then(res => {
console.log(res) // 成功了,很开心
})失败时调用 reject:
js
const p = new Promise((resolve, reject) => {
setTimeout(() => {
reject('嘤嘤嘤')
}, 1000)
})
p.catch(err => {
console.log(err) // 嘤嘤嘤
})调试时,一秒后 .then() 或 .catch() 中的打印执行,说明状态已经改变并触发了对应回调。
易错点:成功结果不要写到 .catch() 里;.catch() 不是只捕获语法错误,它接收的是 reject 传出的失败结果。
状态一旦敲定就不能再改
笔记强调:每个 Promise 对象一旦被兑现或拒绝,就是已敲定了,状态无法再被改变。
为什么需要:如果状态可以反复改变,同一个异步操作就可能既走成功又走失败,外部处理会混乱。
怎么想:Promise 表示“一个异步操作的最终完成或失败及其结果值”,既然叫“最终”,就只认第一次敲定。
怎么做:调试时先调用 reject,再调用 resolve:
js
const p = new Promise((resolve, reject) => {
setTimeout(() => {
reject('失败了')
resolve('我又成功了')
}, 1000)
})
p.then(res => {
console.log(res)
}).catch(err => {
console.log(err) // 失败了
})结果 .catch() 打印失败信息,后面的 resolve('我又成功了') 没有再传递出去;在控制台查看 p,状态仍然是 rejected。
易错点:不要在一个 Promise 里既 resolve 又 reject 还期待两次都生效;第一次敲定后,后续改变无效。
小结与自测
- Promise 对象有哪 3 种状态?
答案
- 待定 pending,已兑现 fulfilled,已拒绝 rejected
- Promise 状态有什么用?
答案
- 状态改变后,用于关联对应的处理函数:fulfilled 触发 then,rejected 触发 catch
目标与整体思路
这一节要把前面学过的 Promise 和 XHR 结合起来:用 Promise 管理 XHR 异步请求,获取省份列表并渲染到页面。为什么需要这样做?因为 XHR 本身通过事件回调拿结果,代码一多就容易分散;Promise 可以把“请求成功/失败”统一成 then/catch 两条路径,后续再封装接口也更自然。
怎么想?在这一节反复强调:Promise 里放什么异步操作都可以,之前放定时器,现在换成 XHR。XHR 请求成功后调用 resolve(数据),失败后调用 reject(错误信息),外部用 .then() 接收数据、用 .catch() 处理异常。
怎么做?先完成核心功能:创建 Promise → 在回调函数中执行 XHR → 成功后 resolve → .then() 中渲染。再加异常处理:用 xhr.status 判断 200~299,成功才解析数据,否则 reject(new Error(xhr.response))。
易错点:不要忘记 xhr.send();判断成功不能只写 status === 200;JSON.parse 要放在成功分支里,否则 404 时返回 HTML 文本会解析报错。
核心功能:请求省份列表并渲染
为什么需要先做核心功能?因为只有先跑通“请求—传值—渲染”,才能知道 Promise 到底在管理哪一步。的设计是:XHR 代码写在 Promise 构造函数的回调里,Promise 实例化时这段逻辑立刻执行,请求也就发出去了。
怎么想?数据来自服务器,所以第一步在 Promise 回调中创建 XMLHttpRequest,调用 open 设置方法和地址,监听 loadend,再 send。拿到 xhr.response 后,为了外部使用方便,先在内部 JSON.parse 转成对象,再通过 resolve 传出去。
怎么做?核心代码结构如下:
js
const p = new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('get', '省份列表接口地址');
xhr.addEventListener('loadend', () => {
console.log(xhr.response);
const data = JSON.parse(xhr.response);
resolve(data);
});
xhr.send();
});
p.then(res => {
document.querySelector('.box').innerHTML = res.list;
});调试时先在 loadend 里打印响应,确认数据已经回来;再在 .then() 里打印 res,点开后发现真正要渲染的是 res.list,最后用 innerHTML 写进 .box。
易错点:open 只是配置请求,必须再调用 send;监听事件名是 loadend;如果外部还要做其他处理,内部先转好 JSON 对象会更方便。
调试异常:从 200 到 404
为什么需要专门调试异常?因为真实请求不一定成功,必须知道失败时状态码和响应内容长什么样。先打印 xhr.status,正常请求得到 200;然后把 URL 后面加上 123 制造错误地址,再次请求得到 404。
怎么想?AJAX 判断响应成功不是看“有没有拿到文字”,而是看 HTTP 状态码。笔记小结也明确:响应状态码大于等于 200 且小于 300 才算成功。404 表示找不到资源,属于失败。
怎么做?在 loadend 中先判断:
js
if (xhr.status >= 200 && xhr.status < 300) {
const data = JSON.parse(xhr.response);
resolve(data);
} else {
reject(new Error(xhr.response));
}演示时发现:错误地址下 xhr.response 是一段 HTML 文本,里面有 404 not find 之类提示;如果仍然直接 JSON.parse,就会报错。所以必须把解析放到成功分支里。
易错点:不要写成只等于 200;不要先 JSON.parse 再判断状态码;失败时传出去的信息要包装成错误对象,方便 .catch() 统一处理。
异常处理:catch 中接收并渲染错误信息
为什么要把异常传给 catch?因为 Promise 的成功走 .then(),失败走 .catch()。在 Promise 基础部分讲过:调用 resolve 对应 .then(),调用 reject 对应 .catch()。这里失败分支调用 reject(new Error(xhr.response)),外部 .catch() 就能拿到错误对象。
怎么想?最终页面要显示的是错误提示文本,而不是整个错误对象。用 console.dir(err) 查看对象结构,点开后找到 message 属性,再把 err.message 渲染到 .box。
怎么做?完整结构如下:
js
const p = new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('get', '省份列表接口地址');
xhr.addEventListener('loadend', () => {
if (xhr.status >= 200 && xhr.status < 300) {
const data = JSON.parse(xhr.response);
resolve(data);
} else {
reject(new Error(xhr.response));
}
});
xhr.send();
});
p.then(res => {
document.querySelector('.box').innerHTML = res.list;
}).catch(err => {
console.dir(err);
document.querySelector('.box').innerHTML = err.message;
});易错点:catch 里不要直接拿 err 当字符串用,要取 err.message;渲染错误信息时页面盒子类名要和 HTML 对上;演示 404 后记得把 URL 改回正确地址。
小结
这一节的关键不是背代码,而是理解 Promise 如何管理 XHR:异步请求写在 Promise 回调里,成功 resolve 数据,失败 reject 错误;外部用 .then() 渲染省份列表,用 .catch() 渲染异常提示。判断请求成功看状态码是否在 200~299 范围内。把这条链路跑通后,后面再封装类似 hmAxios 的函数就有了基础。
代码示例
代码 1:Promise 基础用法(定时器模拟异步任务)
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>认识 Promise</title>
</head>
<body>
<script>
// 1. 实例化 Promise 对象:传入的回调函数在实例化时「立刻执行」
const p = new Promise((resolve, reject) => {
// 2. 执行异步操作(这里用定时器模拟),并传递结果
setTimeout(() => {
const isOk = true
if (isOk) {
resolve('成功了,很开心') // 成功 -> 状态变成 fulfilled
} else {
reject('嘤嘤嘤失败了') // 失败 -> 状态变成 rejected
}
}, 1000)
})
// 3. 接收结果:resolve 对应 then,reject 对应 catch
p.then(res => {
console.log('then 收到成功结果:', res)
}).catch(err => {
console.log('catch 收到失败结果:', err)
})
// 观察状态变化:pending -> fulfilled / rejected(且不可再变)
console.log('实例化后立刻打印 p:', p) // 此时 promiseState 为 pending
setTimeout(() => {
console.log('1.5 秒后再打印 p:', p) // 此时已是 fulfilled 或 rejected
}, 1500)
</script>
</body>
</html>要点解释与易错点
new Promise((resolve, reject) => {...})里的回调函数是同步立刻执行的,异步代码(定时器、XHR)写在它内部。resolve传出的值只会进入then的参数;reject传出的值只会进入catch的参数,两两对应,别记反。- 在控制台展开 Promise 对象可以看到
promiseState属性:pending(待定)/fulfilled(已兑现)/rejected(已拒绝)。 - 易错点:状态一旦从
pending变成fulfilled或rejected就敲定了,之后再调reject(或resolve)不会生效,也不会触发对应回调。 - 易错点:只写
then不写catch,失败时控制台会报未捕获的错误。
代码 2:Promise 管理 XHR —— 获取省份列表并渲染(核心功能)
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>Promise + XHR 获取省份列表</title>
</head>
<body>
<button>获取省份列表</button>
<div class="box"></div>
<script>
// 换成你自己的「获取省份列表」接口地址
const URL = 'http://hmajax.itheima.net/api/province'
document.querySelector('button').addEventListener('click', () => {
// 1. 创建 Promise 对象,把 XHR 异步任务写在回调函数里
const p = new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest()
xhr.open('GET', URL)
// 监听 loadend 事件:响应回来后执行
xhr.addEventListener('loadend', () => {
// 2. 传递数据:把 JSON 字符串先转成 JS 对象,外面就不用再转了
resolve(JSON.parse(xhr.response))
})
// 别忘了发送请求
xhr.send()
})
// 3. 接收并使用数据
p.then(res => {
console.log(res)
document.querySelector('.box').innerHTML = res.list
})
})
</script>
</body>
</html>要点解释与易错点
- 要把某个异步任务交给 Promise 管理,就把它整段写进
new Promise的回调函数里;这里替换了上一段的定时器,位置完全一样。 xhr.addEventListener('loadend', ...)在响应回来后触发,xhr.response是 JSON 字符串,先JSON.parse再resolve出去。- 易错点:忘记写
xhr.send(),请求根本发不出去,loadend永远不会触发,then也就永远不执行。 - 易错点:
open的第一个参数是请求方法('GET'),第二个才是地址,顺序写反会直接报错。 res.list是数组,直接赋给innerHTML会被转成字符串拼接展示,笔记中就是这么渲染的。
代码 3:Promise + XHR 异常处理(状态码判断 + catch 渲染错误信息)
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>Promise + XHR 异常处理</title>
</head>
<body>
<button>请求省份列表(异常演示)</button>
<div class="box"></div>
<script>
// 故意写错地址,制造 404 异常;改回正确地址即可验证成功分支
const URL = 'http://hmajax.itheima.net/api/province123'
document.querySelector('button').addEventListener('click', () => {
const p = new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest()
xhr.open('GET', URL)
xhr.addEventListener('loadend', () => {
// 2.1 判断请求是否成功:状态码 200 ~ 299 为成功
if (xhr.status >= 200 && xhr.status < 300) {
resolve(JSON.parse(xhr.response))
} else {
// 2.2 传递异常信息:包装成 Error 对象再 reject
reject(new Error(xhr.response))
}
})
xhr.send()
})
// 3. 接收并处理:成功走 then,失败走 catch
p.then(res => {
document.querySelector('.box').innerHTML = res.list
}).catch(err => {
console.dir(err) // 用 dir 才能展开看到 message
document.querySelector('.box').innerHTML = err.message
})
})
</script>
</body>
</html>要点解释与易错点
- 成功与否靠
xhr.status(响应状态码)判断:>= 200 && < 300才算成功,404属于「找不到」。 - 失败分支必须调用
reject(...),catch里的回调才会执行;不调reject,catch永远不会跑。 - 把服务器返回的文本用
new Error(xhr.response)包装后再传出,外部拿到的是标准错误对象,统一从err.message取信息。 - 易错点:用
console.log(err)打印错误对象看不到message属性内容,要换成console.dir(err)展开查看。 - 易错点:异常时
xhr.response是一段 HTML 文本,用innerHTML渲染才会显示成页面元素(笔记中演示的就是渲染出带 404 提示的标签)。 - 易错点:错误分支里不要再执行
JSON.parse(xhr.response),格式不对会抛出解析异常。
常见错误
1. then 里的回调永远不执行,页面也没动静
- 现象:
p.then(...)写了,控制台一直没输出,Promise 对象展开后state仍是pending。 - 原因:异步分支里漏调了
resolve/reject;用 XHR 时则是open之后忘了send(),loadend根本不触发。 - 修法:检查回调函数中每条执行路径是否都有
resolve或reject;XHR 写完open立刻补send()。
2. 以为 resolve() 是 return,后面的代码照样执行
- 现象:
resolve('成功')之后又跑了console.log、又发了第二次请求。 - 原因:
resolve只负责改状态 + 派发结果,不会中断函数执行。 - 修法:成功分支写
return resolve(...),失败分支写return reject(...),或直接用if / else把两条路隔开。
3. 只写 then 不写 catch,控制台报 Uncaught (in promise)
- 现象:请求失败时页面无提示,只有一行红色报错,用户看到的是空白。
- 原因:
reject抛出的结果没有对应的catch接收,被当成未处理的拒绝。 - 修法:
then与catch成对书写;即便暂时不处理失败,也要写catch兜底。
4. 404 也进了 then,异常信息渲染不出来
- 现象:把 URL 改错,
then依然执行,页面显示一堆解析失败的报错。 - 原因:没判断
xhr.status,或写成了status === 200,把 201、204 等也判成失败。 - 修法:统一用区间判断
status >= 200 && status < 300,命中走resolve,否则走reject。
5. catch 里拿到 err,err.message 是 undefined
- 现象:
catch(err => box.innerHTML = err.message)渲染出undefined。 - 原因:
reject('服务器错误')传的是字符串而不是错误对象,字符串没有message属性。 - 修法:统一
reject(new Error(xhr.response));调试时用console.dir(err)展开对象确认属性名。
6. then 里 res.list 是 undefined
- 现象:数据打印出来是一长串字符串,取
.list拿不到数组。 - 原因:
resolve出去的是xhr.response原始 JSON 文本,没解析就传给了外部。 - 修法:在 Promise 内部
JSON.parse(xhr.response)后再resolve,让 then 只拿现成对象。
7. 状态已敲定后又调 reject,catch 不执行
- 现象:代码里
resolve和reject都调了,只有 then 生效,catch 静默。 - 原因:Promise 状态一旦从
pending变为fulfilled或rejected就锁定,后续调用被忽略。 - 修法:保证成功/失败两条分支互斥(用
if / else),不要在同一路径上先后调用两者。
练习
练习 1|把定时器装进 Promise 要求:用 new Promise 包装一个 2 秒定时器,成功时 resolve 一个对象 { code: 200, msg: '完成' };外部用 then 打印 msg。写完后把 resolve 改成 reject(new Error('超时')),补上 catch,让失败信息也能打印出来。
练习 2|改造回调式 XHR 给出这样一段代码:
js
function getProvinces() {
const xhr = new XMLHttpRequest()
xhr.open('GET', 'http://hmajax.itheima.net/api/province')
xhr.addEventListener('loadend', () => {
console.log(xhr.response)
})
xhr.send()
}要求:改造成 getProvinces() 返回 Promise 的版本,调用方写成 getProvinces().then(res => ...).catch(err => ...),并保证 then 里拿到的已经是 JS 对象,不是 JSON 字符串。
练习 3|找错并说明 下面代码有三处问题,请指出并给出修正后的完整写法:
js
const p = new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest()
xhr.open('GET', 'http://hmajax.itheima.net/api/province')
xhr.addEventListener('loadend', () => {
resolve(xhr.response)
if (xhr.status === 200) reject(new Error('失败'))
})
})
p.then(res => console.log(res.list))提示方向:请求是否发出、成功判断是否严谨、成功与失败是否互斥。
练习 4|异常信息上屏 要求:请求一个错误的地址(在原 URL 后随意加字符),在 catch 中把服务器返回的错误文本渲染到 .box 容器里,且页面上只出现提示文字本身,不出现 Error: 前缀、不出现 undefined。写完后说明你用 console.log 还是 console.dir 定位属性,为什么。
练习 5|状态推演 不看运行结果,先写出下面代码的控制台输出顺序,以及最后 p 的状态,再上机验证:
js
const p = new Promise((resolve, reject) => {
console.log('A')
setTimeout(() => {
reject(new Error('x'))
resolve('y')
}, 0)
})
p.then(v => console.log('then', v))
p.catch(e => console.log('catch', e.message))
console.log('B')原视频对照
| # | 视频 | 时长 |
|---|---|---|
| 1 | 认识-Promise | 08:16 |
| 2 | 了解-Promise的状态 | 09:53 |
| 3 | 案例-使用Promise加XHR获取省份列表-核心功能 | 09:12 |
| 4 | 案例-使用Promise加XHR获取省份列表-异常处理 | 10:44 |
小结
- Promise 的真正价值是把"产出结果"和"消费结果"拆开:任务内部只负责产出,外部只负责处理,两边互不关心对方怎么写。
resolve/reject是"派发结果 + 改状态",不是return,写在其后的同步代码仍会执行,靠return或if / else才能截断。- 状态一旦敲定不可逆,所以成功与失败必须设计成互斥分支,任何"两个都调"的写法都是在埋雷。
then与catch要成对出现——不写catch不等于没有错误,只是错误变成了控制台里没人管的红色报错。- 数据要在
resolve之前处理干净(如JSON.parse),then里只做业务,这样后续换成 axios 时逻辑几乎不用改。 - XHR 的成功判断是 2xx 区间而不是等于 200;"Promise 永远 pending"最常见的原因不是 Promise 写错,而是
send()忘了调。 - 错误一律用
Error对象传递,保留message,这是catch里能统一处理、统一展示的前提。 - Promise 本身并不会消灭回调,它只是把回调从"嵌套"改成"串联";真正让代码变平的,是后面基于它的链式调用与
async / await。