引言
JavaScript 是单线程语言,这意味着它一次只能执行一个任务。但是,通过异步编程,我们可以实现非阻塞的操作,提高程序的性能和用户体验。
回调函数(Callback)
基本概念
回调函数是最早的异步编程方式:
1 2 3 4 5 6 7 8 9 10
| function fetchData(callback) { setTimeout(() => { const data = 'Hello World'; callback(data); }, 1000); }
fetchData((data) => { console.log(data); });
|
回调地狱
当多个异步操作嵌套时,会出现回调地狱:
1 2 3 4 5 6 7 8 9
| getData(function(a) { getMoreData(a, function(b) { getMoreData(b, function(c) { getMoreData(c, function(d) { console.log(d); }); }); }); });
|
Promise
基本用法
Promise 是 ES6 引入的异步编程解决方案:
1 2 3 4 5 6 7 8 9 10 11
| const promise = new Promise((resolve, reject) => { setTimeout(() => { resolve('Success!'); }, 1000); });
promise.then((value) => { console.log(value); }).catch((error) => { console.error(error); });
|
Promise 链式调用
1 2 3 4
| fetchUser() .then(user => fetchOrders(user.id)) .then(orders => console.log(orders)) .catch(error => console.error(error));
|
Promise.all
并行执行多个 Promise:
1 2 3 4 5 6 7
| Promise.all([ fetchUser(), fetchOrders(), fetchProducts() ]).then(([user, orders, products]) => { console.log(user, orders, products); });
|
async/await
基本语法
async/await 是 ES2017 引入的语法糖,让异步代码看起来像同步代码:
1 2 3 4 5 6 7 8 9
| async function getUserData() { try { const user = await fetchUser(); const orders = await fetchOrders(user.id); return orders; } catch (error) { console.error(error); } }
|
并行执行
1 2 3 4 5 6 7 8 9
| async function getAllData() { const [users, orders, products] = await Promise.all([ fetchUsers(), fetchOrders(), fetchProducts() ]); return { users, orders, products }; }
|
实际应用示例
数据获取
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| async function fetchUserProfile(userId) { try { const response = await fetch(`/api/users/${userId}`); if (!response.ok) { throw new Error('Network response was not ok'); } const userData = await response.json(); return userData; } catch (error) { console.error('Fetch error:', error); throw error; } }
|
文件读取(Node.js)
1 2 3 4 5 6 7 8 9 10 11 12
| const fs = require('fs').promises;
async function readConfigFile() { try { const data = await fs.readFile('config.json', 'utf8'); const config = JSON.parse(data); return config; } catch (error) { console.error('Error reading config:', error); return null; } }
|
最佳实践
- 优先使用 async/await,代码更易读
- 正确处理错误,使用 try/catch
- 避免 await 在循环中串行执行,使用 Promise.all
- 及时清理资源,避免内存泄漏
总结
| 特性 |
回调函数 |
Promise |
async/await |
| 可读性 |
差 |
一般 |
好 |
| 错误处理 |
复杂 |
较好 |
好 |
| 调试 |
困难 |
一般 |
容易 |
| 浏览器支持 |
所有 |
现代浏览器 |
现代浏览器 |
异步编程是 JavaScript 开发中必须掌握的技能,希望本文能帮助你更好地理解和使用它!