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. 同步代码 → 立即执行
  2. 异步代码 → 进入任务队列
  3. 同步全部执行完 → 再执行异步队列

一句话:先同步,后异步


六、生产级应用场景

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 异步方式

  1. 回调函数
  2. Promise
  3. async / await(生产标准)

生产应用

接口请求、文件上传、定时器、事件监听、消息通知、性能优化。