Skip to content

JavaScript 异步编程

什么是异步编程

JavaScript 是单线程语言,但通过异步编程可以处理非阻塞操作,提高程序性能。

回调函数(Callback)

基本概念

javascript
function fetchData(callback) {
    setTimeout(() => {
        const data = "获取到的数据";
        callback(data);
    }, 1000);
}

fetchData(function(result) {
    console.log(result); // 1秒后输出:获取到的数据
});

回调地狱问题

javascript
// 多层嵌套的回调,难以维护
getData(function(a) {
    getMoreData(a, function(b) {
        getEvenMoreData(b, function(c) {
            // 更多嵌套...
        });
    });
});

Promise

基本用法

javascript
const promise = new Promise((resolve, reject) => {
    setTimeout(() => {
        const success = true;
        if (success) {
            resolve("操作成功");
        } else {
            reject("操作失败");
        }
    }, 1000);
});

promise
    .then(result => console.log(result))
    .catch(error => console.error(error));

Promise 链式调用

javascript
fetchUserData()
    .then(user => fetchUserPosts(user.id))
    .then(posts => fetchPostComments(posts[0].id))
    .then(comments => console.log(comments))
    .catch(error => console.error(error));

Promise.all 和 Promise.race

javascript
// 等待所有 Promise 完成
Promise.all([
    fetchData1(),
    fetchData2(),
    fetchData3()
]).then(results => {
    console.log("所有数据都获取完成:", results);
});

// 等待第一个 Promise 完成
Promise.race([
    fetchData1(),
    fetchData2()
]).then(result => {
    console.log("第一个完成的结果:", result);
});

async/await

基本语法

javascript
async function fetchData() {
    try {
        const result = await someAsyncOperation();
        console.log(result);
    } catch (error) {
        console.error(error);
    }
}

实际应用示例

javascript
async function getUserProfile(userId) {
    try {
        const user = await fetch(`/api/users/${userId}`);
        const userData = await user.json();
        
        const posts = await fetch(`/api/users/${userId}/posts`);
        const postsData = await posts.json();
        
        return {
            user: userData,
            posts: postsData
        };
    } catch (error) {
        console.error("获取用户资料失败:", error);
        throw error;
    }
}

// 使用
getUserProfile(123)
    .then(profile => console.log(profile))
    .catch(error => console.error(error));

异步模式对比

方式优点缺点
回调函数简单直接回调地狱,难以维护
Promise链式调用,错误处理语法相对复杂
async/await语法简洁,易读需要现代浏览器支持

实际应用场景

1. 网络请求

javascript
async function loadUserData() {
    const response = await fetch('/api/user');
    const userData = await response.json();
    return userData;
}

2. 文件操作(Node.js)

javascript
const fs = require('fs').promises;

async function readFile() {
    try {
        const data = await fs.readFile('file.txt', 'utf8');
        console.log(data);
    } catch (error) {
        console.error('读取文件失败:', error);
    }
}

3. 定时器

javascript
function delay(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

async function delayedOperation() {
    console.log("开始操作");
    await delay(2000);
    console.log("操作完成");
}

最佳实践

  1. 优先使用 async/await:语法更清晰
  2. 正确处理错误:使用 try-catch 或 .catch()
  3. 避免过度嵌套:合理使用 Promise.all()
  4. 考虑性能:避免不必要的串行操作

总结

异步编程是现代 JavaScript 开发的核心技能,掌握 Promise 和 async/await 可以让你写出更高效、更易维护的代码。