JavaScript异步编程:初学者完全指南

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

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

开始课程

异步编程在JavaScript中的介绍

JavaScript是一种单线程编程语言,具有非阻塞输入输出模型。这意味着在任意时刻只能执行一个操作。然而,得益于异步编程,Node.js可以在不阻塞主线程的情况下同时处理数千个请求。在本文中,我们将解析异步的主要概念:回调(callbacks)、承诺(Promises)和async/await语法。



什么是异步编程以及为什么需要它?

想象一下你点了一份披萨。如果你站在柜台前等着它做好——这就是同步代码。其他一切都会停止。异步的方式是——你下了单然后去做自己的事情。当披萨做好时,他们会叫你。JavaScript正是这样工作的:它不会等待操作完成(如读取文件、向服务器发送请求),而是继续执行后面的代码。当操作完成时,会调用一个特殊的函数——回调函数。



在Node.js中,异步编程尤其重要,因为服务器必须同时服务多个客户端。如果没有异步,每个新请求都会阻塞整个应用程序的运行。



同步代码 vs 异步代码:示例

来看一个简单的文件读取示例。同步版本会阻塞执行:

const fs = require('fs');

// 同步读取——阻塞线程 const data = fs.readFileSync('file.txt', 'utf8'); console.log('数据已读取:', data); console.log('这段代码只有在文件读取完成后才会执行');


异步版本不会阻塞:

const fs = require('fs');

// 异步读取——不阻塞 fs.readFile('file.txt', 'utf8', (err, data) => { if (err) throw err; console.log('数据已读取:', data); }); console.log('这段代码会立即执行,无需等待文件读取完成');


处理异步的主要方式

在JavaScript(以及Node.js)中,主要有三种异步编程的方式。我们将从最古老到最现代的顺序来介绍它们。



1. 回调函数(Callbacks)

回调函数是一种作为参数传递给另一个函数,并在异步操作完成后被调用的函数。这是最基本且最古老的方法。

function getUserData(userId, callback) {
  setTimeout(() => {
    const user = { id: userId, name: '安娜' };
    callback(null, user); // 第一个参数是错误(如果有的话)
  }, 1000);
}

getUserData(1, (err, user) => {
  if (err) {
    console.error('错误:', err);
    return;
  }
  console.log('用户:', user.name);
});


问题:当操作变多时,代码会变成"回调地狱"(callback hell)——深度嵌套的函数,难以阅读和调试。



2. Promise(承诺)

Promise是一个代表异步操作结果的对象。它可以处于以下三种状态之一:

  • pending(等待中)——操作尚未完成
  • fulfilled(已完成)——操作成功完成
  • rejected(已拒绝)——操作因错误而完成


Promise解决了回调地狱的问题,使代码更加线性:

function getUserData(userId) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const user = { id: userId, name: '伊万' };
      // resolve —— 成功,reject —— 错误
      resolve(user);
      // reject(new Error('用户未找到'));
    }, 1000);
  });
}

// 使用 .then() 链式调用
getUserData(1)
  .then(user => {
    console.log('用户:', user.name);
    return user.id;
  })
  .then(id => console.log('ID:', id))
  .catch(err => console.error('错误:', err))
  .finally(() => console.log('操作已完成'));

博客

书籍推荐