本课聚焦前端异步编程终极方案async/await与ES6模块化,是异步编程的收尾与进阶内容。async/await依托Promise,用同步写法实现异步逻辑,彻底解决回调嵌套和链式调用繁琐问题,是当前项目主流异步写法。模块化则解决代码混乱、全局污染、复用性差的痛点,实现代码规范化拆分。课程通过基础异步、并行执行、模块化拆分三类案例,串联起完整的高级异步开发流程,帮助建立工程化思维。掌握本课内容,既能写出简洁健壮的异步代码,又能搭建规范的项目结构,适配主流前端开发规范,也是面试高频考点,为后续框架学习打下坚实底层基础。
一、课程学习目的
-
理解async/await的底层依托,掌握其作为Promise语法糖的核心特性,彻底告别回调嵌套。
-
熟练使用async/await编写同步风格的异步代码,实现异步任务的串行、并行执行。
-
掌握try/catch捕获async/await异常的规范写法,保障异步逻辑稳定性。
-
理解JS模块化的意义,学会ES6模块化(export/import)的基础用法,实现代码拆分与复用。
-
结合async/await与模块化,搭建规范的异步项目结构,为工程化开发奠定基础。
二、核心知识点讲解
1. async/await 基础认知
async/await是ES7推出的Promise语法糖,基于Promise实现,让异步代码写法完全同步化,可读性和可维护性远超原生Promise链式调用。
核心规则:
-
async:修饰函数,标记该函数为异步函数,内部可使用await,函数默认返回Promise对象。
-
await:只能在async函数内使用,暂停代码执行,等待右侧Promise状态变更后再继续。
2. async/await 执行与异常处理
await会等待Promise返回结果,成功则直接获取resolve值,失败则抛出异常;必须配合try/catch捕获错误,避免程序崩溃。
3. ES6 模块化基础
模块化用于拆分代码、避免全局污染、实现功能复用,是前端工程化的基础。
核心语法:
-
export:导出模块内的变量、函数、类,分为默认导出(export default)和按需导出。
-
import:导入其他模块的内容,配合script type="module"使用。
4. async/await 结合模块化
将异步请求、工具函数封装为独立模块,通过import引入,在async函数内调用await执行,实现逻辑解耦、代码复用。
三、示例程序
示例1:async/await 基础用法
javascript
// 复用第15课Promise封装
function getWordInfo(word) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (word) resolve({ en: word, cn: '中文释义' });
else reject('单词不能为空');
}, 1000);
});
}
// async修饰异步函数
async function fetchWord() {
// try/catch捕获异常
try {
// await等待Promise结果,同步写法
const res1 = await getWordInfo('apple');
console.log('第一个单词:', res1);
const res2 = await getWordInfo('banana');
console.log('第二个单词:', res2);
} catch (err) {
// 捕获await抛出的错误
console.error('异步失败:', err);
}
}
// 调用异步函数
fetchWord();
示例2:async/await 并行执行
javascript
async function fetchAllWord() {
try {
// Promise.all实现并行,await等待全部结果
const results = await Promise.all([
getWordInfo('apple'),
getWordInfo('banana'),
getWordInfo('orange')
]);
console.log('全部单词:', results);
} catch (err) {
console.error('加载失败:', err);
}
}
fetchAllWord();
示例3:ES6模块化拆分
javascript
// wordModule.js 模块文件(导出)
// 异步函数封装
export async function getWord(word) {
try {
const res = await fetch(`/api/word?name=${word}`);
return res.json();
} catch (err) {
throw err;
}
}
// 默认导出
export default {
getWord
};
// 主文件 index.js 导入
import { getWord } from './wordModule.js';
async function init() {
const data = await getWord('grape');
console.log(data);
}
init();
四、掌握技巧与方法
-
await必须写在async函数内,禁止在全局或普通函数中单独使用。
-
所有await逻辑都要包裹try/catch,规范捕获异步异常,避免未处理错误。
-
无依赖的异步任务用Promise.all+await并行执行,提升加载效率。
-
模块化拆分遵循单一职责,异步逻辑、工具函数、业务逻辑分开封装。
-
浏览器中使用ES6模块化,script标签需添加type="module"属性。
-
async函数返回的Promise可继续链式调用,灵活适配复杂场景。
五、课后作业
基础作业
-
用async/await改写第15课Promise链式调用代码,实现串行获取单词。
-
使用try/catch捕获async/await的异常,测试失败场景。
-
编写async函数,通过await+Promise.all并行加载3组数据。
进阶作业
-
将Promise异步函数拆分为独立模块,用import导入并通过await调用。
-
实现异步加载的加载状态、成功、失败三种页面反馈。
-
在async函数内实现异步任务超时中断逻辑。
实战作业
- 搭建模块化异步单词查询页面,拆分异步请求模块、渲染模块,用async/await处理异步逻辑,实现加载提示、错误兜底、数据展示全流程。
上一课:异步编程进阶(Promise)实战作业代码
代码功能说明
本实战代码围绕Promise核心知识点,采用英语单词加载场景,实现完整的异步处理流程。代码封装Promise异步函数,模拟网络请求延迟获取单词数据,支持单个单词查询、链式串行加载、多单词并行加载三大功能,搭配页面加载状态、成功渲染、错误提示交互,直观展示Promise三种状态流转、then/catch/finally用法,以及Promise.all并行执行逻辑。页面配备功能按钮,点击可分步演示各类异步场景,全程贴合第15课核心考点,对比回调函数优势,为async/await学习做好铺垫。
注意事项
-
Promise状态一旦从pending变为fulfilled/rejected,不可再次修改,resolve/reject仅调用一次。
-
必须添加catch捕获异常,避免未处理的Promise错误导致页面逻辑中断。
-
链式调用时,then内部需返回新Promise,才能实现异步串行执行。
-
Promise.all中任一任务失败,整体会进入catch,需做好单个任务异常兜底。
-
finally常用于关闭加载状态、清理定时器,无论成功失败都会执行。
-
调试时打开浏览器控制台,观察Promise状态变化与执行时序,加深理解。
-
禁止在Promise执行器内编写同步阻塞代码,保证异步特性。
完整实战代码
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>第15课 Promise实战 - 单词异步加载器</title>
<style>
.box {
width: 750px;
margin: 50px auto;
padding: 30px;
border: 1px solid #eee;
border-radius: 10px;
font-family: "Microsoft YaHei";
box-shadow: 0 0 12px rgba(0,0,0,0.06);
}
.btn {
padding: 10px 20px;
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: 20px;
line-height: 2;
border-top: 1px dashed #eee;
min-height: 180px;
}
.item {
margin: 8px 0;
padding: 10px;
background: #f9f9f9;
border-radius: 5px;
}
.loading {
color: #666;
}
.error {
color: #f56c6c;
}
</style>
</head>
<body>
<div class="box">
<h2>Promise单词异步加载器</h2>
<button class="btn" onclick="getSingleWord()">单个单词查询</button>
<button class="btn" onclick="getSeriesWord()">串行链式加载</button>
<button class="btn" onclick="getAllWord()">并行批量加载</button>
<button class="btn" onclick="clearResult()">清空结果</button>
<div class="result" id="result"></div>
</div>
<script>
const resDom = document.getElementById("result");
// 渲染函数
function render(html, className = '') {
resDom.innerHTML += `<div class="item ${className}">${html}</div>`;
}
// 清空结果
function clearResult() {
resDom.innerHTML = "";
}
// Promise封装:异步获取单词
function fetchWord(word) {
return new Promise((resolve, reject) => {
render(`正在加载:${word}`, 'loading');
// 模拟网络延迟
setTimeout(() => {
if (word && typeof word === 'string') {
// 成功
resolve({ en: word, cn: '对应中文释义', status: 'success' });
} else {
// 失败
reject('单词参数无效,加载失败');
}
}, 1500);
});
}
// 1. 单个单词查询
function getSingleWord() {
fetchWord('apple')
.then(res => {
render(`成功:${res.en} - ${res.cn}`);
})
.catch(err => {
render(`错误:${err}`, 'error');
})
.finally(() => {
render('单次查询任务结束');
});
}
// 2. 链式串行加载
function getSeriesWord() {
fetchWord('apple')
.then(res => {
render(`成功1:${res.en} - ${res.cn}`);
return fetchWord('banana');
})
.then(res => {
render(`成功2:${res.en} - ${res.cn}`);
return fetchWord('orange');
})
.then(res => {
render(`成功3:${res.en} - ${res.cn}`);
})
.catch(err => {
render(`错误:${err}`, 'error');
});
}
// 3. 并行批量加载
function getAllWord() {
const taskList = [fetchWord('apple'), fetchWord('banana'), fetchWord('grape')];
Promise.all(taskList)
.then(results => {
results.forEach((res, index) => {
render(`批量成功${index+1}:${res.en} - ${res.cn}`);
});
})
.catch(err => {
render(`批量错误:${err}`, 'error');
});
}
</script>
</body>
</html>
作业验收标准
-
所有功能按钮点击正常,无控制台报错,加载、成功、错误状态展示清晰。
-
单个查询、串行链式、并行批量逻辑执行准确,符合Promise执行规则。
-
异常捕获到位,错误提示友好,finally收尾逻辑正常执行。
-
代码规范、注释完整,贴合第15课Promise核心知识点,交互简洁直观。