I/O 是 Input/Output(输入/输出)的缩写,指计算机系统与外部世界或其他设备进行数据交换的过程。在编程中,I/O 操作通常涉及从外部源读取数据(输入)或将数据发送到外部目标(输出)。
核心概念
- 输入(Input):从外部获取数据
- 示例:读取文件、接收网络请求、获取键盘输入、接收传感器数据
- 输出(Output):向外部发送数据
- 示例:写入文件、发送网络请求、屏幕显示内容、控制打印机
JavaScript 中的常见 I/O 操作
| 类型 | 浏览器环境示例 | Node.js 环境示例 |
|---|---|---|
| 文件 I/O | File API(用户文件上传) | fs.readFile(), fs.writeFile() |
| 网络 I/O | fetch(), WebSocket | http.request(), net 模块 |
| 用户 I/O | onclick, keyboard events | readline 模块(命令行输入) |
| 设备 I/O | 摄像头/麦克风访问 | 硬件通信(通过串行端口库) |
为什么 I/O 操作很特殊?
-
速度极慢(相对于 CPU):

-
不可预测性:
- 受网络延迟、磁盘状态、外部系统响应等影响
- 可能失败(文件不存在、网络断开等)
JavaScript 如何处理 I/O?
由于 JavaScript 是单线程语言,采用 非阻塞 I/O 模型 避免卡住整个程序:
// 同步 I/O(阻塞 - 避免使用!)
const data = fs.readFileSync('file.txt'); // 程序卡住直到完成
// 异步 I/O(非阻塞 - 推荐方式)
fs.readFile('file.txt', (err, data) => {
// 回调函数在 I/O 完成后执行
});
事件循环中的 I/O 处理流程
- 发起 I/O 请求(如 fetch())
- JavaScript 引擎将操作交给底层系统(浏览器/Node.js)
- 主线程继续执行后续代码
- I/O 完成后,结果放入 回调队列
- 事件循环将回调移入调用栈执行

实际代码示例
console.log('启动'); // 同步
// 异步网络 I/O
fetch('https://api.example.com/data')
.then(response => response.json()) // 微任务
.then(data => console.log('收到数据:', data));
// 异步文件 I/O(Node.js)
fs.readFile('config.json', (err, content) => {
console.log('文件内容:', content); // 宏任务
});
console.log('继续执行'); // 同步
执行顺序:
- 启动
- 继续执行
- 收到数据:(微任务优先)
- 文件内容:(宏任务)
为什么 I/O 属于宏任务?
- I/O 回调通常被放入 宏任务队列
- 与微任务的区别:
// 微任务(Promise)
Promise.resolve().then(() => console.log('微任务'));
// 宏任务(I/O回调)
setTimeout(() => console.log('宏任务'), 0);
// 输出顺序:微任务 → 宏任务
I/O 性能优化技巧
- 批量处理:合并多个小 I/O 请求
- 流式处理:使用流(Stream)处理大文件
// Node.js 流示例
fs.createReadStream('bigfile.mp4')
.pipe(fs.createWriteStream('copy.mp4'));
- 缓存机制:减少重复 I/O
- 异步并行:使用 Promise.all() 并发多个 I/O
关键结论:I/O 操作是 JavaScript 异步编程的核心场景,理解其非阻塞特性是掌握事件循环的关键。永远避免同步 I/O,否则会阻塞整个应用!

1166

被折叠的 条评论
为什么被折叠?



