📚 JavaScript 异步编程入门:Promise 与 Async/Await 2024-09-25
文章摘要
📚 JavaScript 异步编程入门:Promise 与 Async/Await
在现代 JavaScript 开发中,异步编程是不可或缺的一部分。本文将为你详细介绍 Promise 和 Async/Await,以及它们在处理异步操作中的应用和区别。🚀
🌀 什么是 Promise?
Promise 是 JavaScript 中处理异步操作的一种机制。它代表了一个可能在未来完成或失败的操作,并允许你在操作完成后处理结果或错误。
🔑 Promise 的关键点:
-
状态:
- Pending(进行中):初始状态,操作尚未完成。
- Fulfilled(已完成):操作成功完成。
- Rejected(已失败):操作失败。
-
特性:
- 状态不可变:一旦改变状态,就不会再改变。
- 回调自动调用:状态改变后,相关回调自动执行。
🌟 使用示例:
// 创建一个新的 Promise
const promise = new Promise((resolve, reject) => {
// 模拟异步操作
if (/* 操作成功 */) {
resolve(value); // 成功时调用 resolve
} else {
reject(error); // 失败时调用 reject
}
});
// 处理 Promise
promise
.then(value => {
// 操作成功时执行
})
.catch(error => {
// 操作失败时执行
});
⚡ Async/Await
Async/Await 是基于 Promise 的语法糖, introduced in ES2017,旨在让异步代码看起来更像同步代码,从而提高可读性和可维护性。
🔑 关键点:
- async 函数:声明为
async
的函数返回一个Promise
。 - await 关键字:用于等待一个
Promise
解决,并获取其结果。
🌟 使用示例:
async function myAsyncFunction() {
try {
const result = await someAsyncOperation(); // 等待异步操作完成
console.log(result);
} catch (error) {
console.error(error); // 捕获错误
}
}
myAsyncFunction();
🛠️ 适用场景
✅ 适用场景包括:
- 网络请求:如获取数据、提交表单等。
- 文件操作:读写文件。
- 定时器:延迟执行某些操作。
特别适用于需要进行一系列异步操作的场景,例如先从服务器获取数据,再根据数据执行其他操作。🔄
📝 使用技巧
- 错误处理:
- 使用
.catch()
或try/catch
捕获错误,避免未处理的错误。
- 使用
- 链式调用:
- 利用 Promise 的链式特性,保持代码清晰。
- 并行执行:
- 使用
Promise.all()
或Promise.race()
同时处理多个异步操作。
- 使用
- 性能优化:
- 处理大量异步操作时,考虑使用
Web Workers
或streams
提高性能。
- 处理大量异步操作时,考虑使用
💡 示例讲解
以下是一个实际的代码示例,展示了如何在 TypeScript 中结合使用 async/await
、.then
和 try/catch
。
📁 src/utils/auth.ts
// src/utils/auth.ts
// 认证相关的辅助函数
import bcrypt from "bcrypt";
// 加载管理员密码
const ADMIN_PASSWORD_HASH = process.env.ADMIN_PASSWORD_HASH || "";
/**
* 验证管理员密码
* @param password 明文密码
* @returns 是否验证成功
*/
export async function verifyPassword(password: string): Promise<boolean> {
return bcrypt.compare(password, ADMIN_PASSWORD_HASH);
}
/**
* 设置管理员密码(用于生成 ADMIN_PASSWORD_HASH)
* @param password 明文密码
* @returns 哈希后的密码
*/
export async function hashPassword(password: string): Promise<string> {
const saltRounds = 10;
const hash = await bcrypt.hash(password, saltRounds);
return hash;
}
📄 详细注释的代码案例
// src/utils/auth.ts
// 认证相关的辅助函数
import bcrypt from "bcrypt";
// 从环境变量中加载管理员的密码哈希值
const ADMIN_PASSWORD_HASH = process.env.ADMIN_PASSWORD_HASH || "";
/**
* 验证管理员密码
* @param password 明文密码
* @returns 是否验证成功
*/
export async function verifyPassword(password: string): Promise<boolean> {
try {
// 使用 bcrypt.compare 比较明文密码和存储的哈希值
return await bcrypt.compare(password, ADMIN_PASSWORD_HASH)
.then(result => {
return result; // 返回比较结果(布尔值)
});
} catch (error) {
// 捕获并处理可能的错误
console.error("Password verification failed:", error);
return false; // 验证失败时返回 false
}
}
/**
* 设置管理员密码(用于生成 ADMIN_PASSWORD_HASH)
* @param password 明文密码
* @returns 哈希后的密码
*/
export async function hashPassword(password: string): Promise<string> {
const saltRounds = 10; // 定义盐值轮数,用于增强哈希的安全性
// 使用 bcrypt.hash 对明文密码进行哈希处理
const hash = await bcrypt.hash(password, saltRounds);
return hash; // 返回哈希后的密码
}
📄 同步与异步操作的例子
以下示例展示了在等待异步操作时,其他函数如何继续执行,而不被阻塞。
// src/utils/asyncExample.ts
// 示例文件,展示 async/await 与 Promise 的使用
/**
* 模拟一个耗时的异步操作,比如网络请求
* @param delay 延迟时间(毫秒)
* @returns Promise<void> 在指定延迟后解决
*/
function simulateAsyncOperation(delay: number): Promise<void> {
return new Promise<void>(resolve => {
setTimeout(resolve, delay); // 使用 setTimeout 模拟延迟
});
}
/**
* Function 1:启动后等待2秒后完成
*/
function function1(): void {
console.log("Function 1 started");
simulateAsyncOperation(2000).then(() => {
console.log("Function 1 completed after 2 seconds");
});
}
/**
* Function 2:启动后等待1.5秒后完成
*/
function function2(): void {
console.log("Function 2 started");
simulateAsyncOperation(1500).then(() => {
console.log("Function 2 completed after 1.5 seconds");
});
}
/**
* Function 3:异步函数,等待3秒后完成
*/
async function function3(): Promise<void> {
console.log("Function 3 started");
try {
await simulateAsyncOperation(3000); // 等待异步操作完成
console.log("Function 3 completed after 3 seconds");
} catch (error) {
console.error("An error occurred in Function 3:", error);
}
}
/**
* Function 4:立即完成,没有异步操作
*/
function function4(): void {
console.log("Function 4 started");
console.log("Function 4 completed immediately");
}
/**
* 主函数:同时调用多个函数,观察执行顺序
*/
function main(): void {
console.log("Main function started");
function1();
function2();
function3();
function4();
console.log("Main function completed");
}
main();
📄 运行结果
Main function started
Function 1 started
Function 2 started
Function 3 started
Function 4 started
Function 4 completed immediately
Function 2 completed after 1.5 seconds
Function 1 completed after 2 seconds
Function 3 completed after 3 seconds
Main function completed
🧩 总结
- Promise 和 Async/Await 是 JavaScript 中处理异步操作的核心工具。它们使代码更加清晰、可读和易于维护。
- Promise 适用于简单的异步操作和链式调用,而 Async/Await 提供了更直观的异步代码编写方式。
- 在实际开发中,选择合适的方式处理异步操作,可以显著提高代码质量和开发效率。✨
希望这篇文章能帮助你更好地理解 JavaScript 的异步编程概念,祝你编程愉快!💻🎉