模式切换
异步编程与回调
异步编程与回调
异步编程是计算机程序设计中的一种处理程序执行流程的方式,主要用于处理时间较长的操作(如 I/O 操作、网络请求等),在这些操作完成之前,不会阻塞程序的执行。
同步和异步
同步(Synchronous):同步编程中的操作是按顺序执行的。每一个操作都会等待前一个操作完成后再继续执行,因此它们是阻塞式的。
示例:
javascriptconsole.log("开始"); console.log("执行操作1"); console.log("执行操作2"); console.log("结束");
上述代码是同步执行的,输出将是:
开始 执行操作1 执行操作2 结束
异步(Asynchronous):异步编程中的操作在执行时不会等待前一个操作完成,可以继续执行后面的任务。当某个操作完成时,回调函数会被调用,通知程序去处理结果。
示例:
javascriptconsole.log("开始"); setTimeout(() => { console.log("异步操作1"); }, 2000); console.log("结束");
上述代码是异步执行的,输出将是:
开始 结束 异步操作1
回调函数
回调函数(Callback)是指作为参数传递给另一个函数的函数,它会在特定的操作完成后被调用。回调函数常用于处理异步操作的结果。
回调函数的示例
javascript
function fetchData(callback) {
setTimeout(() => {
const data = "数据加载完毕";
callback(data); // 回调函数被调用
}, 2000);
}
fetchData((result) => {
console.log(result); // 输出:"数据加载完毕"
});
在上述示例中,fetchData
函数模拟了一个异步操作,操作完成后通过回调函数返回数据。
回调地狱(Callback Hell)
回调函数的嵌套很容易导致“回调地狱”,即多个回调函数层层嵌套,使得代码难以阅读和维护。
示例:
javascriptasyncFunction1((result1) => { asyncFunction2(result1, (result2) => { asyncFunction3(result2, (result3) => { asyncFunction4(result3, (result4) => { console.log(result4); }); }); }); });
使用 async/await 的异步编程
Promise 基础
Promise
是一种更现代的异步编程解决方案,它表示异步操作的最终完成(或失败)及其结果值。Promise
有三种状态:
- Pending(待定):操作尚未完成。
- Fulfilled(已完成):操作成功完成,返回结果。
- Rejected(已拒绝):操作失败,返回错误。
Promise 的用法
javascript
let promise = new Promise((resolve, reject) => {
const isSuccessful = true; // 模拟操作结果
if (isSuccessful) {
resolve("操作成功");
} else {
reject("操作失败");
}
});
promise
.then((result) => {
console.log(result); // 输出:操作成功
})
.catch((error) => {
console.log(error); // 输出:操作失败
});
为什么使用 async/await
async/await
是基于 Promise
的语法糖,使得异步代码写起来像同步代码一样简洁、直观。使用 async/await
可以避免回调地狱,提高代码的可读性和可维护性。
- 优点:
- 代码更加简洁,避免回调地狱。
- 使得异步操作看起来像同步操作,逻辑更容易理解。
- 错误处理更加直观,可以使用
try/catch
来捕获错误。
async/await 的使用
- 定义:
async
:用来声明一个异步函数,async
函数总是返回一个Promise
。await
:只能在async
函数内使用,用于等待Promise
解决。
javascript
async function fetchData() {
const data = await new Promise((resolve, reject) => {
setTimeout(() => resolve("数据加载完毕"), 2000);
});
console.log(data); // 输出:"数据加载完毕"
}
fetchData();
在上述示例中,await
等待 Promise
完成后,才会继续执行后面的代码。
使用 async/await 异步编程的优点
代码简洁易懂: 使用
async/await
后,代码更接近同步代码,逻辑更清晰。避免回调地狱: 使用
await
使得多层回调嵌套变得平坦,减少了回调地狱问题。统一的错误处理: 错误处理可以通过
try/catch
来统一管理,避免了.catch()
和回调函数的错误处理混用。
示例:
javascriptasync function fetchData() { try { const data1 = await new Promise((resolve) => setTimeout(() => resolve("数据1"), 1000)); const data2 = await new Promise((resolve) => setTimeout(() => resolve("数据2"), 1000)); console.log(data1, data2); // 输出:数据1 数据2 } catch (error) { console.error("发生错误:", error); } } fetchData();
- 支持串行和并行执行:
- 串行执行:在
await
语句上等待,确保每个异步操作按顺序执行。 - 并行执行:可以使用
Promise.all()
来并行执行多个异步操作,从而提高效率。
- 串行执行:在
串行执行:
javascriptasync function serialExecution() { const result1 = await asyncTask1(); const result2 = await asyncTask2(); console.log(result1, result2); }
并行执行:
javascriptasync function parallelExecution() { const [result1, result2] = await Promise.all([asyncTask1(), asyncTask2()]); console.log(result1, result2); }