javascript中异步与同步
一、同步(Synchronous)
1. 定义
程序按照代码书写顺序,一行一行执行。
必须等上一行执行完毕,下一行才能开始。
2. 核心特点
- 顺序执行
- 阻塞执行(前一步没做完,后面全部等待)
- 逻辑直观、流程明确
- 资源利用率低(CPU/网络 空等)
3. 生活例子
把大象装进冰箱:
1. 打开冰箱门
2. 把大象放进去
3. 关上冰箱门
必须一步做完,才能做下一步。中间不能干别的。
4. 代码表现
console.log(1)
console.log(2) // 必须等 1 执行完
console.log(3) // 必须等 2 执行完
二、异步(Asynchronous)
1. 定义
程序不必等待上一个操作完成,可以先去做别的事情。
当上一个操作完成后,系统会通知你回来处理结果。
2. 核心特点
- 非阻塞
- 并发/并行执行
- 资源利用率极高
- 代码逻辑更复杂
- 需要:回调、Promise、async/await
3. 生活例子
上班打卡:
8 点整,100 个员工同时到公司,各自打卡,互不等待。
打卡机后台统一记录。
这就是典型异步并发。
4. 为什么 JS 需要异步?
因为 JS 是单线程语言。
如果不使用异步:
- 发送网络请求时页面会卡死
- 定时器会阻塞代码
- 文件读取会卡住整个程序
所以:JS 所有耗时操作必须异步。
三、同步 vs 异步 对比
| 特性 | 同步 | 异步 |
|---|---|---|
| 执行方式 | 顺序执行 | 非阻塞、并发执行 |
| 阻塞 | 阻塞后续代码 | 不阻塞 |
| 资源利用 | 低 | 高 |
| 代码复杂度 | 简单 | 复杂 |
| 适用场景 | 简单逻辑、计算 | 网络请求、文件IO、定时器 |
| 代表API | for、if、while | ajax/fetch、setTimeout |
四、JavaScript 异步发展史
1. 回调函数(最早异步方案)
setTimeout(() => {
console.log('异步完成')
}, 1000)
问题:回调地狱(Callback Hell)
多层嵌套代码难以维护。
2. Promise(ES6 标准,生产主流)
解决回调地狱。
function request() {
return new Promise((resolve) => {
setTimeout(() => resolve('数据'), 1000)
})
}
request().then(res => console.log(res))
3. async / await(ES7,最终方案)
异步代码写得像同步一样。
async function fetchData() {
let res = await request()
console.log(res)
}
五、JS 异步底层运行机制
JS 异步依靠 事件循环(Event Loop) 实现:
- 同步代码 → 立即执行
- 异步代码 → 进入任务队列
- 同步全部执行完 → 再执行异步队列
一句话:先同步,后异步。
六、生产级应用场景
1. 网络请求(最常用)
- 接口请求
- 获取列表、提交表单
- 登录、支付、上传文件
async function getList() {
let res = await axios.get('/api/list')
}
2. 文件操作
- 上传图片/视频
- 读取本地文件
- 大文件分片上传
3. 定时器/延迟执行
- 验证码倒计时
- 自动关闭弹窗
- 轮询请求
4. DOM 渲染 & 事件
- 点击事件
- 滚动加载
- 表单输入防抖
5. 跨页面通信
- 消息监听
- 广播通知
6. 微任务/宏任务控制
- 保证执行顺序
- 性能优化
七、总结
- 同步:按顺序、阻塞、简单
- 异步:非阻塞、并发、高效
- JS 单线程 → 必须异步才能不卡顿
- 现代 JS 异步 = Promise + async/await
- 生产 90% 异步场景:网络请求、文件操作、定时器
同步
顺序执行、阻塞、逻辑简单、资源利用率低。
异步
非阻塞、并发执行、资源利用率高、代码更复杂,依靠回调/Promise/async-await 实现。
JS 为什么必须异步
JS 是单线程,耗时操作(网络、IO、定时器)必须异步,否则会阻塞页面。
JS 异步方式
- 回调函数
- Promise
- async / await(生产标准)
生产应用
接口请求、文件上传、定时器、事件监听、消息通知、性能优化。