JavaScript基础课程十七、异步编程进阶(Promise)
本课聚焦JavaScript异步编程进阶核心Promise,针对回调地狱的痛点,讲解Promise的状态机制、基础语法与链式调用。Promise通过pending、fulfilled、rejected三种状态管理异步流程,用then/catch替代嵌套回调,让代码结构更清晰、更易维护。课程结合单词查询场景,拆解基础封装、串行链式、并行执行三类案例,帮助掌握Promise的实战用法。Promise是前端异步处理的标准方案,也是面试高频考点,更是后续学习async/await的必备基础。掌握本课内容,既能解决项目中的异步嵌套问题,又能建立规范的异步编程思维,为前端工程化开发打下关键基础。
一、课程学习目的
-
回顾回调函数的弊端,深刻理解回调地狱对代码维护的影响。
-
掌握Promise的核心概念、三种状态流转机制,吃透异步处理的底层逻辑。
-
熟练使用Promise基础语法、then/catch/finally链式调用,规范处理异步结果。
-
学会Promise.all、Promise.race等常用API,实现异步任务串行与并行执行。
-
能够封装Promise异步函数,替代传统回调写法,为后续async/await学习筑牢基础。
二、核心知识点讲解
1. 回调地狱与Promise诞生
上一课学习的回调函数,在处理多层异步任务时会形成横向嵌套的回调地狱,导致代码可读性差、难以调试、维护成本极高。
Promise是ES6推出的异步处理对象,通过状态管理和链式调用,将嵌套回调改写为线性结构,彻底解决回调地狱问题,让异步代码更接近同步写法。
2. Promise的三种状态(不可逆)
-
pending(等待态):初始状态,异步任务执行中,未得到结果
-
fulfilled(成功态):异步任务完成,调用resolve方法,触发then处理结果
-
rejected(失败态):异步任务失败,调用reject方法,触发catch捕获错误
状态一旦从pending变为fulfilled/rejected,就会固定不变,无法再次修改。
3. Promise基础语法与执行流程
创建Promise实例时,需要传入一个执行器函数,内部包含resolve和reject两个参数,分别用于标记成功和失败。
调用Promise实例后,通过then接收成功结果,catch捕获异常错误,finally无论成功失败都会执行。
4. Promise核心API与用法
-
.then():处理成功态结果,支持返回新Promise,实现链式调用
-
.catch():捕获失败态错误,全局捕获整条链的异常
-
.finally():收尾执行,常用于关闭加载、清理状态
-
Promise.all():并行执行多个Promise,全部成功才返回结果
-
Promise.race():并行执行多个Promise,以最快完成的结果为准
三、示例程序
示例1:Promise基础封装(异步查询单词)
// 封装异步获取单词的Promise函数
function getWordInfo(word) {
// 返回Promise实例
return new Promise((resolve, reject) => {
// 模拟网络请求延迟
setTimeout(() => {
// 判断异步任务是否成功
if (word && typeof word === 'string') {
// 成功:返回单词数据
resolve({ en: word, cn: '中文释义', status: 'success' });
} else {
// 失败:返回错误信息
reject(new Error('单词参数无效,获取失败'));
}
}, 1000);
});
}
// 调用Promise并处理结果
getWordInfo('apple')
.then(res => {
console.log('获取成功:', res);
})
.catch(err => {
console.error('获取失败:', err.message);
})
.finally(() => {
console.log('异步任务执行完毕');
});
示例2:Promise链式调用(串行获取单词)
// 链式调用,按顺序执行异步任务
getWordInfo('apple')
.then(res => {
console.log('第一个单词:', res.en);
// 返回新Promise,继续下一个任务
return getWordInfo('banana');
})
.then(res => {
console.log('第二个单词:', res.en);
return getWordInfo('orange');
})
.then(res => {
console.log('第三个单词:', res.en);
})
// 全局捕获整条链的错误
.catch(err => {
console.error('任务中断:', err.message);
});
示例3:Promise.all并行获取单词
// 创建多个Promise任务
const task1 = getWordInfo('apple');
const task2 = getWordInfo('banana');
const task3 = getWordInfo('grape');
// 并行执行,全部完成后统一处理
Promise.all([task1, task2, task3])
.then(results => {
console.log('全部单词获取成功:', results);
})
.catch(err => {
console.error('有任务失败:', err.message);
});
四、掌握技巧与方法
-
异步耗时任务(定时器、接口请求、文件加载)优先用Promise封装,替代回调函数。
-
牢记Promise状态不可逆,resolve和reject仅能调用一次,避免重复触发。
-
链式调用时,then内部需返回新Promise,否则无法实现异步串行。
-
必须添加catch捕获错误,防止未处理的Promise异常导致代码崩溃。
-
多个无依赖异步任务用Promise.all并行执行,提升效率;有依赖任务用链式串行。
-
调试时重点观察状态流转,区分pending、fulfilled、rejected的执行时机。
五、课后作业
基础作业
-
用Promise封装定时器异步任务,1.5秒后返回指定数据。
-
调用Promise,分别测试成功、失败两种场景,验证then和catch的执行逻辑。
-
使用finally方法,测试异步任务完成后的收尾逻辑。
进阶作业
-
实现Promise链式调用,按顺序获取3组单词数据。
-
用Promise.all并行加载多个单词,处理全部成功的场景。
-
模拟异步失败场景,验证catch的全局捕获能力。
实战作业
- 搭建可视化异步单词加载页面,用Promise封装异步逻辑,实现单个加载、串行加载、并行加载功能,搭配加载状态和错误提示,完成完整实战。
上一课:异步编程基础(回调函数)实战作业
代码功能说明
本实战代码围绕回调函数核心知识点,贴合英语单词场景设计,可直接在浏览器运行。代码封装了同步回调、异步定时器回调、事件回调三类函数,模拟单词同步处理、延迟加载、点击触发加载的逻辑,直观展示同步与异步代码的执行顺序差异,演示回调函数处理异步结果的流程,同时通过多层嵌套回调展现回调地狱的结构,帮助理解回调函数的用法与弊端。页面配备功能按钮,点击可分步演示不同回调场景,结果实时渲染,全程衔接第14课知识点,为后续学习Promise做好铺垫。
注意事项
-
同步代码优先级高于异步代码,异步回调会在主线程空闲后执行,需牢记执行顺序。
-
回调函数需在异步任务完成后调用,确保结果获取准确,避免时序错误。
-
多层嵌套回调会形成回调地狱,导致代码可读性差,仅用于理解痛点,项目不推荐使用。
-
异步任务的错误需通过回调参数传递,无法直接用try/catch捕获,需做好异常判断。
-
回调函数内部this易指向全局,可通过箭头函数或缓存this变量修正指向。
-
运行代码时打开浏览器控制台,可更清晰观察异步执行流程与回调触发时机。
-
本案例为基础入门,复杂异步场景建议使用后续课程的Promise方案优化。
完整实战代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>第14课 回调函数实战 - 单词加载器</title>
<style>
.box {
width: 700px;
margin: 50px auto;
padding: 25px;
border: 1px solid #eee;
border-radius: 10px;
font-family: "Microsoft YaHei";
box-shadow: 0 0 10px rgba(0,0,0,0.05);
}
.btn {
padding: 10px 18px;
margin: 10px 8px;
background: #42b983;
color: #fff;
border: none;
border-radius: 6px;
cursor: pointer;
transition: 0.3s;
}
.btn:hover {
background: #359469;
}
.result {
margin-top: 25px;
padding: 15px;
line-height: 2;
border-top: 1px dashed #eee;
min-height: 150px;
}
.item {
margin: 8px 0;
padding: 10px;
background: #f9f9f9;
border-radius: 5px;
}
</style>
</head>
<body>
<div class="box">
<h2>单词加载器(回调函数版)</h2>
<button class="btn" onclick="testSyncCallback()">同步回调</button>
<button class="btn" onclick="testAsyncCallback()">异步回调</button>
<button class="btn" onclick="testCallbackHell()">回调地狱演示</button>
<button class="btn" onclick="clearResult()">清空结果</button>
<div class="result" id="result"></div>
</div>
<script>
const resultDom = document.getElementById("result");
// 渲染结果到页面
function render(html) {
resultDom.innerHTML += `<div class="item">${html}</div>`;
}
// 1. 同步回调函数
function getWord(word, callback) {
callback(word);
}
function testSyncCallback() {
getWord("apple", function(res) {
render(`同步回调结果:获取单词 - ${res}`);
});
render("同步代码执行完毕");
}
// 2. 异步回调函数(定时器模拟)
function getWordAsync(word, delay, callback) {
render(`正在异步加载单词:${word},延迟${delay}ms`);
setTimeout(() => {
callback(res);
}, delay);
}
function testAsyncCallback() {
getWordAsync("banana", 1500, function(res) {
render(`异步回调结果:获取单词 - ${res}`);
});
render("异步任务已发起,继续执行同步代码");
}
// 3. 回调地狱演示(多层嵌套)
function testCallbackHell() {
getWordAsync("apple", 1000, function(res1) {
render(res1);
getWordAsync("banana", 1000, function(res2) {
render(res2);
getWordAsync("orange", 1000, function(res3) {
render(res3);
});
});
});
}
// 清空结果
function clearResult() {
resultDom.innerHTML = "";
}
</script>
</body>
</html>
作业验收标准
-
所有按钮点击正常执行,浏览器控制台无报错。
-
同步回调、异步回调结果展示准确,执行顺序符合异步编程规则。
-
回调地狱演示清晰展现多层嵌套结构,直观体现代码可读性问题。
-
代码规范,注释完整,贴合第14课回调函数核心知识点。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)