在现代前端开发中,异步编程是必不可少的技能。本文将带你深入了解 JavaScript 异步编程的演进历程,从传统的回调函数到现代的 async/await。
异步编程的演进
1. 回调函数时代
在 ES6 之前,JavaScript 主要使用回调函数处理异步操作:
// ES6 之前的回调函数方式
fs.readFile('./1.html', 'utf-8', (err, data) => {
if (err) {
console.log(err);
return;
}
console.log(data);
})
这种方式虽然简单,但容易导致"回调地狱",代码可读性差且难以维护。
2. Promise 的诞生
ES6 引入了 Promise,为异步操作提供了更优雅的解决方案:
const p = new Promise((resolve, reject) => {
fs.readFile('./1.html', 'utf-8', (err, data) => {
if (err) {
reject(err);
return;
}
resolve(data);
})
})
p.then(data => {
console.log(data);
}).catch(err => {
console.log(err);
})
Promise 解决了回调地狱的问题,但链式调用的 .then() 仍然不够直观。
3. Async/Await 的革命
ES8 引入了 async/await,让异步代码看起来像同步代码:
const main = async () => {
const html = await p;
console.log(html);
}
main();
实战:使用 Fetch API 调用大模型
基础 Fetch 用法
// 传统 .then() 方式
fetch('https://api.github.com/users/shunwuyu/repos')
.then(res => {
return res.json();
})
.then(data => {
console.log(data);
})
Async/Await 改进版
// 使用 async/await
const main = async () => {
const res = await fetch('https://api.github.com/users/shunwuyu/repos');
const data = await res.json();
console.log(data);
}
复杂请求:调用 DeepSeek API
// 请求配置
const endpoint = 'https://api.deepseek.com/chat/completions';
const headers = {
'Content-Type': 'application/json',
'Authorization': `Bearer ${import.meta.env.VITE_DEEPSEEK_API_KEY}`
}
const payload = {
'model': 'deepseek-chat',
'messages': [
{
'role': 'system',
'content': 'You are a helpful assistant.'
},
{
'role': 'user',
'content': '你好 DeepSeek'
}
]
}
// 使用 async/await 发送请求
async function fetchData() {
try {
const response = await fetch(endpoint, {
method: 'POST',
headers,
body: JSON.stringify(payload)
});
const data = await response.json();
document.getElementById('reply').textContent = data.choices[0].message.content;
} catch (error) {
console.error('Error fetching data:', error);
document.getElementById('reply').textContent = '请求失败,请检查控制台错误';
}
}
fetchData();
关键概念解析
Fetch API 响应处理
| 名称 | 类型 | 说明 |
|---|---|---|
res | Response | HTTP 响应对象,包含状态码、头部等信息 |
res.json() | Promise | 读取并解析 JSON 的方法 |
data | Object/Array | 解析后的 JavaScript 数据 |
为什么选择 POST 请求
- 安全性:POST 不会将数据暴露在 URL 中
- 数据容量:支持更大的请求体
- 语义明确:适合创建资源的操作
环境变量管理
在前端项目中,敏感信息如 API Key 应该存储在环境变量中:
// 使用 Vite 环境变量
'Authorization': `Bearer ${import.meta.env.VITE_DEEPSEEK_API_KEY}`
最佳实践
- 错误处理:始终使用 try-catch 包装 await 调用
- 模块化:使用
type="module"启用 ES6 模块功能 - 类型检查:确保请求头和请求体格式正确
- 安全考虑:API Key 等敏感信息不要硬编码在代码中
总结
从回调函数到 Promise,再到 async/await,JavaScript 的异步编程变得越来越简洁和直观。async/await 不仅让代码更易读,还大大降低了异步编程的复杂度。在现代前端开发中,掌握这些异步编程技术是必不可少的技能。
通过本文的示例,你可以看到如何使用现代 JavaScript 特性与 AI 大模型进行交互,这在当今的 AI 应用开发中是非常实用的技能。