logo
GitHub

JavaScript 异步编程

异步编程基础

同步与异步

// 同步代码
console.log('开始');
const result = doSomething();
console.log('结果:', result);
console.log('结束');
// 异步代码
console.log('开始');
doSomethingAsync().then(result => {
console.log('结果:', result);
});
console.log('结束');

回调函数

// 基本回调示例
function fetchData(callback) {
setTimeout(() => {
const data = { id: 1, name: 'JavaScript' };
callback(data);
}, 1000);
}
fetchData(data => {
console.log('获取的数据:', data);
});
// 回调地狱示例
getUser(userId, user => {
getOrders(user.id, orders => {
getOrderDetails(orders[0].id, details => {
console.log('订单详情:', details);
});
});
});

Promise

创建 Promise

const promise = new Promise((resolve, reject) => {
// 异步操作
setTimeout(() => {
const random = Math.random();
if (random > 0.5) {
resolve('成功');
} else {
reject('失败');
}
}, 1000);
});
promise
.then(result => console.log(result))
.catch(error => console.error(error));

Promise 链式调用

function fetchUser(id) {
return new Promise((resolve) => {
setTimeout(() => {
resolve({ id, name: 'Alice' });
}, 1000);
});
}
function fetchOrders(userId) {
return new Promise((resolve) => {
setTimeout(() => {
resolve([{ id: 1, userId, product: 'Book' }]);
}, 1000);
});
}
fetchUser(1)
.then(user => fetchOrders(user.id))
.then(orders => console.log('订单:', orders))
.catch(error => console.error('错误:', error));

Promise.all 和 Promise.race

const promise1 = new Promise(resolve => setTimeout(() => resolve(1), 1000));
const promise2 = new Promise(resolve => setTimeout(() => resolve(2), 2000));
const promise3 = new Promise(resolve => setTimeout(() => resolve(3), 3000));
// 等待所有 Promise 完成
Promise.all([promise1, promise2, promise3])
.then(results => console.log('全部完成:', results))
.catch(error => console.error('有一个失败:', error));
// 等待第一个完成的 Promise
Promise.race([promise1, promise2, promise3])
.then(result => console.log('第一个完成:', result))
.catch(error => console.error('第一个失败:', error));

async/await

基本用法

async function fetchUserData() {
try {
const user = await fetchUser(1);
const orders = await fetchOrders(user.id);
console.log('用户订单:', orders);
} catch (error) {
console.error('错误:', error);
}
}
fetchUserData();

并行执行

async function fetchAllData() {
try {
const [users, products] = await Promise.all([
fetchUsers(),
fetchProducts()
]);
console.log('用户:', users);
console.log('产品:', products);
} catch (error) {
console.error('错误:', error);
}
}

实际应用示例

class DataService {
async fetchUserProfile(userId) {
try {
const user = await this.fetchUser(userId);
const orders = await this.fetchOrders(user.id);
const preferences = await this.fetchPreferences(user.id);
return {
user,
orders,
preferences
};
} catch (error) {
console.error('获取用户资料失败:', error);
throw error;
}
}
async fetchUser(id) {
// 模拟 API 调用
return new Promise(resolve => {
setTimeout(() => {
resolve({ id, name: 'Alice' });
}, 1000);
});
}
async fetchOrders(userId) {
return new Promise(resolve => {
setTimeout(() => {
resolve([{ id: 1, userId, product: 'Book' }]);
}, 1000);
});
}
async fetchPreferences(userId) {
return new Promise(resolve => {
setTimeout(() => {
resolve({ theme: 'dark', language: 'zh' });
}, 1000);
});
}
}
// 使用示例
const service = new DataService();
service.fetchUserProfile(1)
.then(profile => console.log('用户资料:', profile))
.catch(error => console.error('错误:', error));

错误处理

Promise 错误处理

fetchData()
.then(data => processData(data))
.then(result => saveData(result))
.catch(error => {
console.error('发生错误:', error);
// 错误恢复逻辑
return fallbackData;
})
.finally(() => {
// 清理工作
console.log('处理完成');
});

async/await 错误处理

async function processUserData() {
try {
const data = await fetchData();
const result = await processData(data);
await saveData(result);
} catch (error) {
console.error('处理用户数据时出错:', error);
// 错误处理逻辑
} finally {
// 清理工作
}
}

练习

  1. 实现一个简单的异步数据加载器
  2. 使用 Promise.all 同时获取多个 API 的数据
  3. 将回调式 API 转换为 Promise 式 API

小结

  • 理解同步和异步编程的区别
  • 掌握回调函数的使用和缺点
  • 熟练使用 Promise 处理异步操作
  • 掌握 async/await 的语法和应用
  • 学会处理异步操作中的错误