JavaScript异步编程:完整指南

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程
```html

JavaScript 异步编程简介



JavaScript 是一种单线程语言,具有非阻塞事件循环(Event Loop)。这意味着在某一时刻只能执行一个操作,但得益于异步机制,我们无需等待慢速任务(如文件读取、API 请求、定时器)完成,即可继续执行其他代码。本文将深入讲解 Node.js 环境中异步编程的所有关键概念,从回调函数到现代 async/await 语法。



异步编程使我们能够构建高性能的服务器端应用程序,在不阻塞主线程的情况下处理数千个请求。理解这一范式是每位 JavaScript 开发者的必备技能。



1. 回调函数与回调地狱问题



历史上,JavaScript 中最早的异步机制是回调函数(callback)——即在异步操作完成后被调用的函数。



简单回调示例



const fs = require('fs');

// 异步读取文件fs.readFile('example.txt', 'utf8', (err, data) => { if (err) { console.error('读取错误:', err); return; } console.log('文件内容:', data);});

console.log('这条消息会比文件内容先出现');


当需要执行多个连续的异步操作时,问题就出现了。回调的嵌套层级不断增加,代码变得难以阅读——这种现象被称为“回调地狱”(Callback Hell)。



回调地狱示例



fs.readFile('file1.txt', (err, data1) => {    if (err) throw err;    fs.readFile('file2.txt', (err, data2) => {        if (err) throw err;        fs.readFile('file3.txt', (err, data3) => {            if (err) throw err;            // 处理所有三个文件            console.log(data1 + data2 + data3);        });    });});


这种代码难以维护、测试和调试。Promise 的出现解决了这一问题。



2. Promise:摆脱回调地狱



Promise(承诺)是一个代表异步操作结果的对象:成功执行(resolve)或失败(reject)。Promise 允许我们构建调用链,使代码更加扁平化和可读。



创建和使用 Promise



// 返回 Promise 的函数const readFilePromise = (filename) => {    return new Promise((resolve, reject) => {        fs.readFile(filename, 'utf8', (err, data) => {            if (err) reject(err);            else resolve(data);        });    });};

// 使用readFilePromise('file1.txt') .then(data => { console.log('文件已读取:', data); return readFilePromise('file2.txt'); }) .then(data => { console.log('第二个文件:', data); }) .catch(err => { console.error('错误:', err); });


Promise.all 和 Promise.race 方法



对于并行执行多个异步操作,有一些实用的静态方法:



  • Promise.all() — 等待所有 Promise 完成。如果至少有一个失败,整个 Promise.all 将进入 rejected 状态。
  • Promise.race() — 返回第一个完成的 Promise 的结果(成功或失败)。
  • Promise.allSettled() — 等待所有 Promise 完成,返回每个 Promise 的结果(成功或失败)。


const promise1 = readFilePromise('file1.txt');const promise2 = readFilePromise('file2.txt');const promise3 = readFilePromise('file3.txt');

Promise.all([promise1, promise2, promise3]) .then(results => { console.log('所有文件已读取:', results); }) .catch(err ```

博客

书籍推荐