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

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

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

开始课程

JavaScript异步编程简介

\n\n

JavaScript是一种单线程编程语言。这意味着在任意时刻只能执行一个操作。然而,如果所有操作都按顺序执行,浏览器在从服务器加载数据或读取文件时就会“卡死”。这正是异步编程发挥作用的地方。

\n\n

异步编程允许执行耗时操作(API请求、文件读取、定时器)而不阻塞主执行线程。代码不会等待任务完成,而是继续执行,结果稍后处理。这是创建快速响应式Node.js应用程序的关键概念。

\n\n

在本指南中,我们将介绍异步编程的三种主要方法:回调、Promise和async/await语法。您将学习如何正确处理异步代码并避免初学者的常见错误。

\n\n

1. 回调(Callbacks):异步的基础

\n\n

回调(callback)是一个作为参数传递给另一个函数的函数,在异步操作完成后被调用。这是JavaScript中最古老、最基本的异步处理方式。

\n\n

setTimeout示例

\n\n

内置函数setTimeout是异步操作的经典示例。它接受一个回调和一个以毫秒为单位的延迟:

\n\n
console.log('开始');\n\nsetTimeout(() => {\n    console.log('2秒过去了');\n}, 2000);\n\nconsole.log('结束');\n\n// 输出:\n// 开始\n// 结束\n// 2秒过去了
\n\n

请注意:“结束”在回调消息之前输出。这就是异步——代码不会等待setTimeout完成。

\n\n

“回调地狱”问题

\n\n

当有大量嵌套的异步操作时,代码变得难以阅读。这种现象称为“回调地狱”(Callback Hell):

\n\n
fs.readFile('file1.txt', (err, data1) => {\n    if (err) throw err;\n    fs.readFile('file2.txt', (err, data2) => {\n        if (err) throw err;\n        fs.readFile('file3.txt', (err, data3) => {\n            if (err) throw err;\n            console.log(data1, data2, data3);\n        });\n    });\n});
\n\n

这样的代码难以维护和调试。幸运的是,现代JavaScript提供了更优雅的解决方案。

\n\n

2. Promise:优雅的异步处理

\n\n

Promise(承诺)是一个表示异步操作结果的对象。Promise可以处于以下三种状态之一:

\n\n
    \n
  • Pending(待定)——初始状态,操作尚未完成
  • \n
  • Fulfilled(已完成)——操作成功完成
  • \n
  • Rejected(已拒绝)——操作以错误结束
  • \n
\n\n

创建和使用Promise

\n\n
const myPromise = new Promise((resolve, reject) => {\n    setTimeout(() => {\n        const success = true;\n        if (success) {\n            resolve('数据已获取');\n        } else {\n            reject('获取数据出错');\n        }\n    }, 2000);\n});\n\nmyPromise\n    .then(result => {\n        console.log(result); // "数据已获取"\n    })\n    .catch(error => {\n        console.error(error); // "获取数据出错"\n    })\n    .finally(() => {\n        console.log('操作完成');\n    });
\n\n

Promise链式调用(Chaining)

\n\n

Promise可以链式调用,从而避免“回调地狱”:

\n\n
function readFile(filename) {\n    return new Promise((resolve, reject) => {\n        fs.readFile(filename, 'utf8', (err, data) => {\n            if (err) reject(err);\n            else resolve(data);\n        });\n    });\n}\n\nreadFile('file1.txt')\n    .then(data1 => {\                

博客

书籍推荐