JavaScript的 async , await 笔记250808
JavaScript 异步编程:async/await 深度解析 和由 ES2017 引入, 是的语法糖等价于👆等价于👇在现代 JavaScript 开发中, 是处理异步操作的核心语法,由 ES2017 引入, 是的语法糖, 它让异步代码拥有同步代码的可读性和可维护性。 核心概念async 函数await 表达式错误处理机制try/catch 模式async/await 可以使用同步的错误处理
JavaScript的 async , await 笔记250808
JavaScript 异步编程:async/await 深度解析
async
和 await
由 ES2017 引入, 是 Promise
的语法糖
async function f() { return 123; }
等价于 function f() { return Promise.resolve(123); }
async function fun() { return "hello" ; }
👆等价于👇function fun() { return Promise.resolve("hello"); }
在现代 JavaScript 开发中,async/await
是处理异步操作的核心语法,由 ES2017 引入, 是 Promise
的语法糖, 它让异步代码拥有同步代码的可读性和可维护性。
核心概念
async 函数
- 声明一个异步函数:
async function myFunction() {}
- 总是返回一个 Promise 对象
- 函数内可以使用
await
关键字
async function fetchData() {
return "Data"; // 等价于 Promise.resolve("Data")
}
fetchData().then(data => console.log(data)); // 输出 "Data"
await 表达式
- 只能在 async 函数内部使用
- 暂停 async 函数执行,等待 Promise 完成
- 返回 Promise 的解析值
- 如果等待的不是 Promise,则直接返回该值
async function getUser() {
const response = await fetch('/api/user');
const user = await response.json();
return user;
}
错误处理机制
try/catch 模式
async/await 可以使用同步的错误处理方式:
async function loadData() {
try {
const data = await fetchData();
const processed = await processData(data);
return processed;
} catch (error) {
console.error("加载失败:", error);
return fallbackData;
} finally {
console.log("加载过程结束");
}
}
错误传播特性
未处理的错误会向外层传播:
async function taskA() {
throw new Error("A失败");
}
async function taskB() {
await taskA(); // 这里会抛出错误
}
taskB().catch(err => console.log(err.message)); // 输出 "A失败"
执行流程解析
微观任务队列
async/await 基于 Promise 的微任务机制:
console.log("开始");
async function asyncTask() {
console.log("async开始");
await Promise.resolve();
console.log("async继续");
}
asyncTask();
Promise.resolve().then(() => console.log("Promise微任务"));
console.log("结束");
// 输出顺序:
// 开始
// async开始
// 结束
// Promise微任务
// async继续
并发执行优化
避免不必要的顺序等待:
// 低效 - 顺序执行
async function sequentialFetch() {
const user = await fetch('/user');
const posts = await fetch('/posts');
return { user, posts };
}
// 高效 - 并发执行
async function parallelFetch() {
const [user, posts] = await Promise.all([
fetch('/user'),
fetch('/posts')
]);
return { user, posts };
}
高级用法与模式
1. 异步迭代
处理数据流或分页请求:
async function processItems(items) {
for await (const item of items) {
await processItem(item);
}
}
2. 顶层 await
在模块中使用顶层 await(ES2022):
// module.js
const data = await fetchData();
export default data;
3. 异步错误边界
创建错误处理包装器:
function withErrorHandling(fn) {
return async (...args) => {
try {
return await fn(...args);
} catch (error) {
console.error("操作失败:", error);
throw error;
}
};
}
const safeFetch = withErrorHandling(fetch);
4. 取消异步操作
使用 AbortController:
async function fetchWithTimeout(url, timeout = 5000) {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeout);
try {
const response = await fetch(url, { signal: controller.signal });
clearTimeout(timeoutId);
return response.json();
} catch (error) {
if (error.name === 'AbortError') {
throw new Error("请求超时");
}
throw error;
}
}
最佳实践指南
1. 避免阻塞陷阱
// 错误:顺序执行独立操作
const a = await getA();
const b = await getB(); // 不依赖a,但会等待
// 正确:并发执行
const [a, b] = await Promise.all([getA(), getB()]);
2. 合理使用 try/catch
// 只捕获必要的错误
async function updateUser(user) {
try {
await validateUser(user);
} catch (error) {
// 只处理验证错误
return { error: "验证失败" };
}
// 其他操作不需要捕获
await saveUser(user);
return { success: true };
}
3. 处理并行任务
// 限制并发数
async function processBatch(items, concurrency = 5) {
const results = [];
for (let i = 0; i < items.length; i += concurrency) {
const batch = items.slice(i, i + concurrency);
const batchResults = await Promise.all(
batch.map(item => processItem(item))
);
results.push(...batchResults);
}
return results;
}
4. 组合 Promise 和 async/await
// 在事件处理中立即执行异步操作
button.addEventListener('click', () => {
(async () => {
try {
const data = await fetchData();
updateUI(data);
} catch (error) {
showError(error);
}
})();
});
常见误区与解决方案
1. 忘记 await
async function saveData() {
const data = fetchData(); // 错误:缺少await
// data是Promise对象,不是实际数据
const data = await fetchData(); // 正确
}
2. 过度顺序化
// 低效写法
async function process() {
const a = await step1();
const b = await step2(a);
const c = await step3(b);
return c;
}
// 优化后
async function optimizedProcess() {
const a = step1(); // 立即开始
const b = step2(await a); // 等待a完成后开始
return step3(await b);
}
3. 错误处理遗漏
// 危险:未处理错误
async function dangerousTask() {
await criticalOperation();
}
// 安全:添加错误处理
async function safeTask() {
try {
await criticalOperation();
} catch (error) {
logError(error);
throw error; // 或者处理错误
}
}
async/await 与 Promise 对比
特性 | Promise | async/await |
---|---|---|
可读性 | 链式调用,嵌套复杂 | 类似同步代码,直观清晰 |
错误处理 | .catch() 方法 |
try/catch 结构 |
调试 | 链式调用调试困难 | 可直接断点调试 |
流程控制 | .then() 链式控制 |
使用标准控制结构 |
返回值 | 总是返回 Promise | 总是返回 Promise |
总结
async/await 是现代 JavaScript 异步编程的核心特性,它:
- 让异步代码拥有同步代码的可读性和可维护性
- 通过 try/catch 提供更自然的错误处理
- 兼容 Promise 所有功能,可混合使用
- 支持高级模式如并发控制、取消操作
- 需要理解其底层基于 Promise 的微任务机制
掌握 async/await 的关键是理解其执行流程和错误处理机制,避免常见陷阱,并合理利用其与 Promise 的组合能力。
1️⃣ 参考 1
在 JavaScript 中,async/await
是处理异步操作的语法糖,基于 Promise 实现,使异步代码更接近同步代码的书写风格。以下是详细解析:
核心概念
-
async
函数- 声明:在函数前添加
async
关键字 - 返回值:总是返回一个 Promise 对象
- 函数内返回普通值 → 自动包装为 resolved 状态的 Promise
- 函数内抛出错误 → 返回 rejected 状态的 Promise
async function foo() { return 42; // 等价于 Promise.resolve(42) } foo().then(console.log); // 输出 42
- 声明:在函数前添加
-
await
表达式- 只能在
async
函数内部使用 - 作用:暂停 async 函数的执行,等待 Promise 完成
- 若 Promise 成功:返回解决值(resolved value)
- 若 Promise 失败:抛出拒绝原因(rejection reason)
async function bar() { const result = await new Promise(resolve => setTimeout(() => resolve("Done!"), 1000) ); console.log(result); // 1秒后输出 "Done!" }
- 只能在
执行流程详解
async function example() {
console.log("Start");
const data = await fetchData(); // 暂停执行,等待 Promise
console.log("Data received:", data);
return "Complete";
}
example()
.then(console.log) // 输出 "Complete"
.catch(console.error);
console.log("After call"); // 先于异步操作输出
执行顺序:
- 输出
"Start"
- 遇到
await
→ 暂停example
函数,交出控制权 - 输出
"After call"
- 当
fetchData()
的 Promise 完成:- 成功:继续执行,输出
"Data received: ..."
- 失败:抛出错误,被
.catch()
捕获
- 成功:继续执行,输出
错误处理
try/catch
捕获同步错误和异步拒绝async function fetchWithError() { try { const data = await fetch("invalid-url"); return data.json(); } catch (err) { console.error("Request failed:", err); // 捕获网络错误或 JSON 解析错误 } }
- 链式
.catch()
fetchWithError() .catch(err => console.error("Fallback:", err));
关键特性
- 非阻塞性
async function parallel() { const [a, b] = await Promise.all([task1(), task2()]); // 并行执行 await task3(); // 顺序执行 }
- 顶层
await
(ES2022)- 在模块顶层直接使用
await
// 模块中 const data = await fetchData(); console.log(data);
- 在模块顶层直接使用
常见误区
await
不会阻塞主线程- 仅暂停当前
async
函数,不影响其他代码执行
- 仅暂停当前
- 忘记
await
async function mistake() { const p = fetchData(); // 缺少 await → 返回 Promise 对象而非结果 console.log(p); // 输出 Promise { <pending> } }
- 循环中的
await
// 顺序执行 (可能低效) for (const url of urls) { await fetch(url); } // 并行执行 (推荐) await Promise.all(urls.map(url => fetch(url)));
最佳实践
- 用
try/catch
替代.then()
链式调用 - 无依赖的异步操作用
Promise.all()
并行处理 - 优先使用
async/await
而非回调函数/Promise 链
浏览器支持:所有现代浏览器(Chrome 55+、Firefox 52+、Safari 10.1+)及 Node.js 7.6+
2️⃣ 参考 2
JavaScript async
和 await
详解
async
和 await
是 ES2017 引入的语法糖,用于简化 Promise 的使用,使异步代码看起来更像同步代码,同时保持非阻塞特性。
核心概念
1. async 函数
- 作用:声明一个异步函数
- 返回值:总是返回一个 Promise 对象
- 函数返回普通值 → 自动包装为 resolved Promise
- 函数抛出错误 → 自动包装为 rejected Promise
- 函数返回 Promise → 直接返回该 Promise
async function basicAsync() {
return 42; // 等同于 Promise.resolve(42)
}
async function rejectedAsync() {
throw new Error("失败"); // 等同于 Promise.reject(new Error("失败"))
}
basicAsync().then(console.log); // 42
rejectedAsync().catch(console.error); // Error: 失败
2. await 表达式
- 作用:暂停异步函数执行,等待 Promise 解决
- 语法:
const result = await promise
- 行为:
- 如果 Promise 成功解决 → 返回解决值
- 如果 Promise 被拒绝 → 抛出拒绝原因(相当于
throw
)
- 限制:只能在
async
函数内部使用
async function fetchUser() {
const response = await fetch('/api/user'); // 等待 fetch 完成
const user = await response.json(); // 等待 JSON 解析
return user;
}
执行流程解析
基本执行顺序
console.log("开始");
async function demo() {
console.log("函数开始");
const result = await Promise.resolve("结果");
console.log("await 完成:", result);
return "完成";
}
demo().then(res => console.log("then:", res));
console.log("结束");
/* 输出顺序:
开始
函数开始
结束
await 完成: 结果
then: 完成
*/
执行机制图解
错误处理
1. try/catch 方式(推荐)
async function fetchData() {
try {
const response = await fetch('/api/data');
if (!response.ok) {
throw new Error('网络响应异常');
}
return await response.json();
} catch (error) {
console.error('请求失败:', error);
return { data: null }; // 降级处理
}
}
2. .catch() 方式
async function loadResource() {
const resource = await fetchResource().catch(handleError);
if (!resource) return;
// 继续处理资源
}
function handleError(error) {
console.error('加载失败:', error);
return null;
}
性能优化技巧
1. 并行执行(避免顺序等待)
// 顺序执行(慢)
async function sequential() {
const user = await fetchUser();
const posts = await fetchPosts(user.id);
return { user, posts };
}
// 并行执行(快)
async function parallel() {
const [user, posts] = await Promise.all([
fetchUser(),
fetchPosts() // 不需要等待用户数据
]);
return { user, posts };
}
2. 提前启动请求
async function loadPage() {
// 提前启动不依赖彼此的数据请求
const userPromise = fetchUser();
const settingsPromise = fetchSettings();
// 处理其他逻辑...
renderHeader();
// 等待需要的数据
const [user, settings] = await Promise.all([
userPromise,
settingsPromise
]);
renderContent(user, settings);
}
高级使用模式
1. 异步迭代器(for-await-of)
async function processItems(items) {
for await (const item of asyncIterator(items)) {
console.log('处理:', item);
await processItem(item); // 可以包含异步操作
}
}
2. 异步构造函数模式
class DataLoader {
constructor() {
// 保存初始化Promise
this.initialized = this.init();
}
async init() {
this.config = await loadConfig();
this.cache = await createCache();
}
async getData() {
await this.initialized; // 确保初始化完成
return fetchData(this.config.endpoint);
}
}
// 使用
const loader = new DataLoader();
loader.getData().then(console.log);
3. 超时控制
function withTimeout(promise, timeout) {
return Promise.race([
promise,
new Promise((_, reject) =>
setTimeout(() => reject(new Error('操作超时')), timeout)
)
]);
}
async function fetchWithTimeout() {
try {
return await withTimeout(fetch('/api'), 5000);
} catch (error) {
if (error.message === '操作超时') {
console.log('请求超时,使用缓存');
return cachedData;
}
throw error;
}
}
常见误区与解决方案
1. 在循环中错误使用 await
// ❌ 错误:顺序执行异步操作,效率低
async function processArray(array) {
for (const item of array) {
await processItem(item); // 每个await都会阻塞循环
}
}
// ✅ 正确:并行处理
async function processArray(array) {
// 并行启动所有操作
const promises = array.map(item => processItem(item));
// 等待所有操作完成
await Promise.all(promises);
}
2. 忘记处理错误
// ❌ 错误:未处理的Promise拒绝
async function unsafeFetch() {
const data = await fetch('/api');
return data.json();
}
// ✅ 正确:添加错误处理
async function safeFetch() {
try {
const response = await fetch('/api');
return await response.json();
} catch (error) {
console.error('请求失败:', error);
return { status: 'error' };
}
}
3. 不必要地使用 await
// ❌ 错误:不必要的await
async function getData() {
const data = await fetchData();
return await processData(data); // 第二个await不必要
}
// ✅ 正确:直接返回Promise
async function getData() {
const data = await fetchData();
return processData(data); // 返回Promise
}
async/await 与 Promise 对比
特性 | Promise | async/await |
---|---|---|
代码结构 | 链式调用 | 同步风格 |
错误处理 | .catch() 方法 |
try/catch 块 |
可读性 | 回调嵌套可能复杂 | 线性执行更清晰 |
调试 | 断点在then回调间跳转 | 像同步代码一样调试 |
循环处理 | 需要Promise.all等辅助 | for-await-of 简化 |
返回值 | 显式返回Promise | 自动包装为Promise |
最佳实践
- 优先使用 async/await 代替 Promise 链式调用
- 始终处理错误 - 使用 try/catch 或 .catch()
- 避免阻塞操作 - 不要在 async 函数中执行长时间同步任务
- 并行化独立操作 - 使用 Promise.all 加速执行
- 合理使用箭头函数 - 简化小规模异步操作:
const fetchData = async () => { const res = await fetch('/data'); return res.json(); };
浏览器与Node.js支持
环境 | 支持版本 |
---|---|
Chrome | 55+ |
Firefox | 52+ |
Safari | 10.1+ |
Edge | 15+ |
Node.js | 7.6+ (8.0+ 完全支持) |
对于旧环境,可使用 Babel 等工具转译 async/await 语法。
总结
async
和 await
使异步代码:
- 更易读 - 类似同步代码的结构
- 更易写 - 减少回调嵌套
- 更易调试 - 错误堆栈更清晰
- 更易维护 - 线性执行流程
虽然本质上是 Promise 的语法糖,但 async/await 显著提高了异步代码的开发体验和可维护性,是现代 JavaScript 异步编程的首选方式。
3️⃣ 参考 3
在 JavaScript 中,async
和 await
是处理异步操作的语法糖,基于 Promise 实现,旨在让异步代码的书写和阅读更接近同步方式。以下是详细解析:
1. ** async 函数**
- 作用:声明一个异步函数,始终返回一个 Promise 对象。
- 行为:
- 函数返回值会被自动包装成
Promise.resolve(value)
- 抛出错误时返回
Promise.reject(error)
- 函数返回值会被自动包装成
- 示例:
async function foo() { return 42; // 等价于 Promise.resolve(42) } foo().then(console.log); // 输出 42
2. ** await 表达式**
- 作用:暂停
async
函数的执行,等待 Promise 完成(resolve/reject)。 - 规则:
- 只能在
async
函数内部使用。 - 等待 Promise 解决后返回结果值。
- 若 Promise 拒绝,抛出错误(可用
try/catch
捕获)。
- 只能在
- 示例:
async function fetchData() { const response = await fetch('https://api.example.com/data'); // 等待请求完成 const data = await response.json(); // 等待 JSON 解析 return data; }
3. 错误处理
- 使用
try/catch
捕获await
的异常:async function loadData() { try { const data = await fetchData(); } catch (error) { console.error("请求失败:", error); } }
- 也可用
.catch()
处理整个 async 函数的错误:loadData().catch(error => console.error(error));
4. 执行机制
- 非阻塞性:
await
不会阻塞主线程,仅暂停当前async
函数的后续代码。 - 微任务调度:当 Promise 解决时,后续代码作为微任务加入队列。
- 示例分析:
console.log("Start"); async function demo() { console.log("Async start"); await Promise.resolve(); // 将后续代码转为微任务 console.log("Async end"); } demo(); console.log("End"); // 输出顺序: // Start → Async start → End → Async end
5. 并行优化
- 避免串行等待:多个独立操作应并行执行以提高效率。
- 使用
Promise.all
:async function fetchAll() { const [user, posts] = await Promise.all([ fetch('/user'), fetch('/posts') ]); // 两个请求并行执行 }
6. 常见误区
- 在顶层使用
await
:
ES2022 支持在模块顶层使用await
(需在模块中):// 模块文件内 const data = await fetchData(); // 合法
- 循环中的
await
:
在循环内使用await
会导致串行执行,需用Promise.all
优化:// 串行(慢): for (const url of urls) { await fetch(url); } // 并行(快): await Promise.all(urls.map(url => fetch(url)));
7. 与传统 Promise 对比
场景 | Promise 写法 | async/await 写法 |
---|---|---|
链式调用 | .then().then() |
顺序书写,无嵌套 |
错误处理 | .catch() |
try/catch 同步风格 |
代码可读性 | 嵌套复杂时难读 | 结构清晰,类似同步代码 |
总结
async
:标记异步函数,隐式返回 Promise。await
:暂停函数执行,等待 Promise 结果。- 优势:以同步形式写异步代码,提升可读性和可维护性。
- 最佳实践:结合
try/catch
处理错误,用Promise.all
优化并行任务。
通过合理使用 async/await
,可显著简化异步逻辑,减少回调地狱,写出更优雅的 JavaScript 代码。
4️⃣ 参考 4
JavaScript 的 async 和 await 详解
async 和 await 是 ES2017 (ES8) 引入的 JavaScript 特性,它们建立在 Promise 之上,提供了更简洁、更直观的方式来处理异步操作。这两个关键字彻底改变了我们编写异步代码的方式,使异步代码看起来更像同步代码。
核心概念
1. async 函数
- 用于声明一个异步函数
- 始终返回一个 Promise 对象
- 函数内部可以使用 await 关键字
async function fetchData() {
return "Data fetched"; // 自动包装为 resolved Promise
}
// 等同于
function fetchData() {
return Promise.resolve("Data fetched");
}
2. await 表达式
- 只能在 async 函数内部使用
- 暂停 async 函数的执行,等待 Promise 解决
- 返回 Promise 的解决值
- 如果 Promise 被拒绝,则抛出错误
async function getUser() {
const response = await fetch('/api/user'); // 等待 fetch 完成
const user = await response.json(); // 等待 JSON 解析
return user;
}
工作原理详解
1. async 函数的行为
async function example() {
console.log("Start");
const result = await new Promise(resolve =>
setTimeout(() => resolve("Done!"), 1000)
);
console.log(result);
return "Finished";
}
const promise = example();
console.log("After calling example");
// 输出顺序:
// Start
// After calling example
// (1秒后) Done!
2. await 的底层机制
await 本质上是一个语法糖,它将代码分割为多个微任务:
// 使用 await 的代码
async function example() {
const a = await task1();
const b = await task2(a);
return b;
}
// 底层等效代码
function example() {
return task1().then(a => {
return task2(a).then(b => {
return b;
});
});
}
错误处理
1. try/catch 方式
async function fetchData() {
try {
const response = await fetch('https://api.example.com/data');
if (!response.ok) {
throw new Error('Network response was not ok');
}
const data = await response.json();
return data;
} catch (error) {
console.error('Fetch error:', error);
// 返回默认值或重新抛出错误
return { defaultValue: true };
}
}
2. 结合 catch 方法
async function loadContent() {
const data = await fetchData().catch(handleError);
if (!data) return; // 处理错误情况
// 使用数据
renderContent(data);
}
function handleError(error) {
console.error('Loading failed:', error);
showErrorMessage();
return null;
}
高级用法与模式
1. 并行执行多个异步操作
async function fetchAllData() {
// 同时启动所有请求
const [user, posts, comments] = await Promise.all([
fetchUser(),
fetchPosts(),
fetchComments()
]);
return { user, posts, comments };
}
2. 循环中的 await
// 顺序执行
async function processItems(items) {
for (const item of items) {
await processItem(item); // 等待每个完成
}
}
// 并行执行
async function processItemsFast(items) {
await Promise.all(items.map(item => processItem(item)));
}
3. 立即执行 async 函数
(async () => {
try {
const result = await someAsyncOperation();
console.log(result);
} catch (error) {
console.error(error);
}
})();
4. 类中的 async 方法
class ApiClient {
constructor(baseUrl) {
this.baseUrl = baseUrl;
}
async get(endpoint) {
const response = await fetch(`${this.baseUrl}/${endpoint}`);
return response.json();
}
async post(endpoint, data) {
const response = await fetch(`${this.baseUrl}/${endpoint}`, {
method: 'POST',
body: JSON.stringify(data)
});
return response.json();
}
}
// 使用示例
const client = new ApiClient('https://api.example.com');
const userData = await client.get('user/123');
性能优化技巧
1. 避免不必要的顺序等待
// 低效 - 顺序执行
async function inefficient() {
const a = await fetchA();
const b = await fetchB(); // 等待 fetchA 完成才开始
return { a, b };
}
// 高效 - 并行执行
async function efficient() {
const [a, b] = await Promise.all([fetchA(), fetchB()]);
return { a, b };
}
2. 使用 Promise 缓存
const userCache = {};
async function getUser(id) {
if (!userCache[id]) {
userCache[id] = fetch(`/api/users/${id}`).then(r => r.json());
}
return userCache[id];
}
3. 控制并发数量
async function runWithConcurrency(tasks, maxConcurrent) {
const results = [];
const executing = [];
for (const task of tasks) {
const p = task().then(r => {
executing.splice(executing.indexOf(p), 1);
return r;
});
results.push(p);
executing.push(p);
if (executing.length >= maxConcurrent) {
await Promise.race(executing);
}
}
return Promise.all(results);
}
常见陷阱与解决方案
1. 忘记 await
async function updateData() {
// 错误:忘记 await
saveToDatabase(data); // 返回的 Promise 未被处理
// 正确
await saveToDatabase(data);
}
2. 循环中意外顺序执行
const urls = ['/data1', '/data2', '/data3'];
// 错误:顺序执行(可能不是预期行为)
urls.forEach(async url => {
const data = await fetch(url);
console.log(data);
});
// 正确:并行执行
await Promise.all(urls.map(async url => {
const data = await fetch(url);
console.log(data);
}));
3. 忽略错误处理
// 危险:未处理的拒绝
async function dangerous() {
const data = await fetchData();
process(data);
}
// 安全:添加错误处理
async function safe() {
try {
const data = await fetchData();
process(data);
} catch (error) {
console.error('Operation failed', error);
}
}
async/await 与 Promise 的对比
1. 可读性比较
// Promise 链
function getUserPosts(userId) {
return fetchUser(userId)
.then(user => fetchPosts(user.id))
.then(posts => processPosts(posts))
.catch(error => console.error(error));
}
// async/await
async function getUserPosts(userId) {
try {
const user = await fetchUser(userId);
const posts = await fetchPosts(user.id);
return processPosts(posts);
} catch (error) {
console.error(error);
}
}
2. 错误处理比较
// Promise 错误处理
fetchData()
.then(process)
.catch(handleError);
// async/await 错误处理
try {
const data = await fetchData();
process(data);
} catch (error) {
handleError(error);
}
浏览器与 Node.js 支持
1. 浏览器支持
- Chrome 55+ (2016)
- Firefox 52+ (2017)
- Safari 10.1+ (2017)
- Edge 15+ (2017)
- Internet Explorer: 不支持
2. Node.js 支持
- Node.js 7.6+ (需要启用 --harmony 标志)
- Node.js 8.0+ 完全支持
3. 向后兼容方案
使用 Babel 转译 async/await:
// .babelrc
{
"presets": ["@babel/preset-env"]
}
最佳实践
- 始终处理错误:使用 try/catch 或 .catch()
- 避免过度顺序化:并行执行独立任务
- 合理命名 async 函数:使用动词前缀如 fetch、load、get
- 文档化异步函数:使用 JSDoc 注释
/** * 获取用户数据 * @async * @param {string} userId - 用户ID * @returns {Promise<Object>} 用户数据对象 */ async function getUser(userId) { // ... }
- 结合传统 Promise:在需要时混合使用
- 优化递归函数:使用尾调用优化
async function processQueue(queue) { while (queue.length > 0) { const item = queue.shift(); await processItem(item); } }
实际应用案例
1. API 请求处理
async function fetchPaginatedData(url) {
let allData = [];
let nextUrl = url;
while (nextUrl) {
const response = await fetch(nextUrl);
if (!response.ok) throw new Error('API request failed');
const data = await response.json();
allData = allData.concat(data.results);
nextUrl = data.next; // 假设 API 返回 next 字段
}
return allData;
}
2. 超时控制
function withTimeout(promise, timeout) {
return new Promise(async (resolve, reject) => {
const timer = setTimeout(() => {
reject(new Error('Operation timed out'));
}, timeout);
try {
const result = await promise;
clearTimeout(timer);
resolve(result);
} catch (error) {
clearTimeout(timer);
reject(error);
}
});
}
// 使用
try {
const data = await withTimeout(fetchData(), 5000);
} catch (error) {
if (error.message === 'Operation timed out') {
// 处理超时
} else {
// 处理其他错误
}
}
3. 逐步加载 UI
async function loadDashboard() {
showLoadingSpinner();
try {
// 并行加载独立部分
const [user, notifications, timeline] = await Promise.all([
loadUserData(),
loadNotifications(),
loadTimeline()
]);
// 顺序加载依赖部分
const recommendations = await loadRecommendations(user.interests);
renderDashboard({ user, notifications, timeline, recommendations });
} catch (error) {
showError(error);
} finally {
hideLoadingSpinner();
}
}
总结
async/await 是现代 JavaScript 异步编程的核心特性:
-
async 函数:
- 声明异步函数
- 总是返回 Promise
- 内部可以使用 await
-
await 表达式:
- 暂停执行直到 Promise 解决
- 返回 Promise 的解决值
- 抛出拒绝原因
-
优势:
- 代码更简洁、可读
- 错误处理更直观(try/catch)
- 调试更简单(调用栈更清晰)
- 逻辑更接近同步代码
-
最佳实践:
- 合理组合并行与顺序执行
- 始终处理潜在错误
- 避免不必要的等待
- 适当使用 Promise 高级特性
-
注意事项:
- 只能在 async 函数中使用 await
- 浏览器兼容性考虑
- 避免阻塞事件循环
async/await 并没有取代 Promise,而是提供了一种更优雅的使用 Promise 的方式。理解其底层机制和适用场景,可以显著提高异步代码的质量和可维护性。
5️⃣ 参考 5
JavaScript 的 async 和 await 详解
async
和 await
是 ES2017(ES8)引入的语法糖,用于简化 Promise 的异步操作,让异步代码拥有同步代码的书写风格,同时保持非阻塞特性。
核心概念
-
async
函数- 声明一个函数为异步函数:
async function foo() {}
- 返回值会被自动包装成
Promise.resolve(value)
- 抛出错误时返回
Promise.reject(error)
async function getData() { return "Hello"; // 等价于 Promise.resolve("Hello") } getData().then(console.log); // 输出 "Hello"
- 声明一个函数为异步函数:
-
await
表达式- 只能在
async
函数内部使用 - 暂停当前
async
函数的执行,等待 Promise 状态变为resolved
- 返回 Promise 成功的结果值
- 若 Promise 被
rejected
,抛出错误(可用try/catch
捕获)
async function fetchData() { const response = await fetch('https://api.example.com/data'); // 等待请求完成 const data = await response.json(); // 等待解析 JSON return data; }
- 只能在
执行流程解析
async function example() {
console.log("Start");
const result = await new Promise((resolve) =>
setTimeout(() => resolve("Done!"), 1000)
);
console.log(result);
console.log("End");
}
example();
console.log("After calling example");
输出顺序:
Start
After calling example
(等待 1 秒)
Done!
End
- 调用
example()
后,函数同步执行到await
时暂停。 - 主线程继续执行外部代码(输出 “After…”)。
- 当 Promise 完成(1 秒后),恢复
example
的执行。
错误处理
使用 try/catch
捕获异步错误:
async function loadData() {
try {
const data = await fetch("invalid-url");
return data.json();
} catch (error) {
console.error("请求失败:", error);
}
}
并行优化
多个独立异步操作时,避免顺序等待:
// 顺序执行(效率低)
async function sequential() {
const a = await task1(); // 等待完成
const b = await task2(); // 再等待
return [a, b];
}
// 并行执行(推荐)
async function parallel() {
const [a, b] = await Promise.all([task1(), task2()]);
return [a, b];
}
常见问题与解决方案
-
循环中的
await
在循环中直接使用await
会导致顺序执行:// 依次等待每个请求完成(慢) for (const url of urls) { const data = await fetch(url); }
优化方案:并行发起请求
const promises = urls.map(url => fetch(url)); const results = await Promise.all(promises);
-
顶层
await
在 ES2022 中,模块顶层可直接使用await
:// 模块中允许 const data = await fetchData(); export default data;
-
await
非 Promise 值await
会将非 Promise 值包装为Promise.resolve(value)
,等同于直接使用该值。
关键特性总结
特性 | 说明 |
---|---|
语法简洁 | 消除回调地狱,代码更线性 |
错误友好 | 用 try/catch 统一处理同步/异步错误 |
基于 Promise | 兼容现有 Promise 生态 |
非阻塞 | 底层仍是异步操作,不阻塞主线程 |
调试方便 | 异步代码栈追踪更清晰 |
使用场景
- 网络请求(
fetch
/axios
) - 文件读写(Node.js 的
fs.promises
) - 数据库操作
- 任何需要顺序执行异步操作的场景
注意:
await
会阻塞当前async
函数内的后续代码,但不会阻塞主线程其他操作。
6️⃣ 参考 6
以下是关于 JavaScript 中 async/await
的详细解析,采用分步说明和代码示例:
一、基本概念
-
async
函数:- 声明方式:
async function foo() {}
或const foo = async () => {}
- 返回值:始终返回一个 Promise 对象
- 返回值处理:
- 若返回非 Promise 值,会自动包装为
Promise.resolve(value)
- 若返回 Promise,则直接传递该 Promise
- 若返回非 Promise 值,会自动包装为
- 声明方式:
-
await
操作符:- 只能在
async
函数内部使用 - 作用:暂停代码执行,等待 Promise 完成
- 返回值:Promise 的 resolved 值
- 错误处理:若 Promise 被 reject,会抛出异常(需用
try/catch
捕获)
- 只能在
二、基础用法示例
示例 1:基本流程
async function fetchData() {
const response = await fetch('https://api.example.com/data'); // 等待请求完成
const data = await response.json(); // 等待 JSON 解析
return data; // 等价于 Promise.resolve(data)
}
fetchData()
.then(data => console.log(data))
.catch(error => console.error(error));
示例 2:错误处理
async function getUser(id) {
try {
const response = await fetch(`/users/${id}`);
if (!response.ok) throw new Error('User not found');
return await response.json();
} catch (error) {
console.error('Fetch failed:', error);
return { defaultUser: 'Guest' }; // 返回默认值
}
}
三、高级技巧
1. 并行执行优化
// ❌ 低效的顺序执行(总耗时 ≈ 1s + 1s = 2s)
async function sequential() {
const a = await task1(); // 1s
const b = await task2(); // 1s
return a + b;
}
// ✅ 高效的并行执行(总耗时 ≈ 1s)
async function parallel() {
const [a, b] = await Promise.all([task1(), task2()]);
return a + b;
}
2. 混合 Promise 链
async function hybridFlow() {
const user = await fetchUser();
return fetchPosts(user.id)
.then(posts => posts.filter(p => p.published))
.catch(() => []);
}
四、关键注意事项
-
错误冒泡:
- 未捕获的
await
异常会导致返回的 Promise 被 reject - 建议始终使用
try/catch
或在调用链末尾添加.catch()
- 未捕获的
-
顶层 await(ES2022+):
// 仅在 ES Modules 中支持 const response = await fetch('/data');
-
调试优势:
- 异步代码在调用栈中保留完整上下文
- 可直接在
await
行设置断点
五、与 Promise 的对比
特性 | Promise 链 | async/await |
---|---|---|
可读性 | 横向发展(链式调用) | 纵向发展(同步式写法) |
错误处理 | .catch() 集中处理 |
try/catch 块处理 |
中间值操作 | 需通过 .then() 传递 |
可直接使用变量 |
调试体验 | 需跟踪异步边界 | 同步代码调试方式 |
六、常见误区
-
忘记 await:
async function broken() { const data = fetchData(); // 错误:未等待,data 是 Promise console.log(data); // 输出 Promise 对象 }
-
过度嵌套:
// 反模式:本可并行执行的任务被序列化 async function nested() { const a = await taskA(); const b = await taskB(a); const c = await taskC(b); return c; }
七、最佳实践
-
保持函数纯净:
// 推荐:分离业务逻辑与异步控制 async function process() { try { const data = await fetchData(); return validate(data); } catch (error) { logError(error); throw new CustomError('Processing failed'); } }
-
合理使用并行:
async function optimized() { const [user, settings] = await Promise.all([ fetchUser(), fetchSettings() ]); return mergeData(user, settings); }
-
类型安全(TypeScript):
async function typedDemo(): Promise<number> { const result: string = await fetchText(); // TS 会提示类型不匹配 return result.length; }
通过掌握这些核心概念和技巧,您可以编写出更清晰、更易维护的异步 JavaScript 代码。建议结合具体业务场景,灵活运用 async/await
的特性。
7️⃣ 参考 7
JavaScript 中 async
与 await
的详解
一、核心概念async
和 await
是 JavaScript 中用于处理异步操作的现代语法,它们基于 Promise,并提供了更直观、更接近同步代码的写法。以下是它们的核心特性:
-
async
函数:- 使用
async
关键字声明的函数会自动返回一个 Promise。 - 即使函数内部没有显式返回
Promise
,JavaScript 会将其结果包装成一个Promise
。 - 示例:
async function getUser() { return { id: 1, name: "张三" }; // 返回值会被自动包装成 Promise } getUser().then(user => console.log(user)); // 输出: { id: 1, name: "张三" }
- 使用
-
await
关键字:- 只能在
async
函数内部使用。 - 用于等待一个
Promise
的完成,暂停当前async
函数的执行,直到Promise
解决(resolve
)或拒绝(reject
)。 - 如果
Promise
被拒绝,await
会抛出异常,可以通过try...catch
捕获。 - 示例:
async function fetchData() { const response = await fetch("https://api.example.com/data"); // 等待网络请求完成 const data = await response.json(); // 等待数据解析 return data; }
- 只能在
二、优势与传统异步方案对比
传统方案 | 问题 | async/await 的解决方案 |
---|---|---|
回调函数(Callback) | 回调地狱(Callback Hell),嵌套过深,代码可读性差。 | 使用 async/await 将嵌套逻辑扁平化,代码结构更清晰。 |
Promise 链式调用 | 链式调用冗长,错误处理分散,中间值传递复杂。 | async/await 结合 try...catch 实现集中错误处理,逻辑更直观。 |
事件监听(Event) | 依赖事件触发,难以管理多个异步操作的依赖关系。 | async/await 可通过 Promise.all 并行执行多个异步操作,或按需串行执行。 |
三、核心用法详解
1. async 函数的定义与调用
- 定义:
async function myAsyncFunction() { // 异步逻辑 }
- 调用:
- 返回值是一个
Promise
,可以通过.then()
或await
获取结果。
myAsyncFunction().then(result => { console.log(result); });
- 返回值是一个
2. await 的使用规则
- 只能在
async
函数中使用:async function example() { const result = await someAsyncFunction(); // 合法 } // 错误示例:顶层作用域中不能使用 await const result = await someAsyncFunction(); // 报错
- 等待非
Promise
值:- 如果
await
后的表达式不是Promise
,会自动将其转换为已解决的Promise
。
async function test() { const value = await 10; // 等价于 await Promise.resolve(10) console.log(value); // 输出: 10 }
- 如果
3. 错误处理
- 使用
try...catch
捕获异常:async function fetchData() { try { const response = await fetch("https://api.example.com/data"); if (!response.ok) throw new Error("请求失败"); const data = await response.json(); return data; } catch (error) { console.error("错误:", error.message); throw error; // 可选:向上抛出错误 } }
4. 并行执行多个异步操作
- 使用
Promise.all
优化性能:async function fetchMultipleData() { const [data1, data2] = await Promise.all([ fetch("https://api.example.com/data1").then(res => res.json()), fetch("https://api.example.com/data2").then(res => res.json()) ]); console.log(data1, data2); }
四、底层原理
1. async 函数的本质
-
返回
Promise
:- 无论函数内部是否返回
Promise
,async
函数的返回值始终是一个Promise
。
async function example() { return 42; // 等价于 return Promise.resolve(42) }
- 无论函数内部是否返回
-
异常处理:
async
函数中抛出的异常会直接导致返回的Promise
进入rejected
状态。
async function errorDemo() { throw new Error("操作失败"); // 等价于 return Promise.reject("操作失败") }
2. await 的作用机制
- 暂停函数执行,不阻塞主线程:
await
会暂停当前async
函数的执行,但不会阻塞其他代码的运行。
async function test() { console.log(1); await new Promise(resolve => setTimeout(resolve, 2000)); console.log(2); } console.log(3); test(); // 输出顺序: 1 -> 3 -> 2
五、常见误区与最佳实践
1. 避免阻塞陷阱
- 错误示例:
async function sequential() { const a = await task1(); // 等待 1s const b = await task2(); // 再等待 1s → 总耗时 2s }
- 正确并行写法:
async function parallel() { const [a, b] = await Promise.all([task1(), task2()]); // 总耗时 1s }
**2. 循环中的 await **
- 错误示例:
for (const url of urls) { await fetch(url); // 每个请求串行执行 }
- 正确并行写法:
const promises = urls.map(url => fetch(url)); await Promise.all(promises); // 所有请求并行执行
**3. 顶层 await **
- ES2022+ 模块支持:
// 模块顶层直接使用 await const data = await fetchData(); export default data;
六、实际应用场景
1. 网络请求
async function getUserPosts(userId) {
const user = await fetch(`/users/${userId}`);
const posts = await fetch(`/posts?userId=${userId}`);
return { user, posts };
}
2. 文件操作(Node.js)
const fs = require("fs").promises;
async function readFiles() {
const file1 = await fs.readFile("file1.txt", "utf8");
const file2 = await fs.readFile("file2.txt", "utf8");
return file1 + file2;
}
3. 定时器控制
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function countdown() {
console.log(3);
await delay(1000);
console.log(2);
await delay(1000);
console.log(1);
}
七、总结
1. async/await 的优势
- 代码更易读:接近同步代码的写法,逻辑清晰。
- 错误处理更友好:使用
try...catch
集中处理错误。 - 调试更方便:调试器可以逐步跟踪每一行代码。
- 性能优化:结合
Promise.all
并行执行异步操作。
2. 与传统方案的对比
方案 | 可读性 | 错误处理 | 性能 | 调试难度 |
---|---|---|---|---|
回调函数 | 低 | 分散 | 高 | 高 |
Promise 链式调用 | 中 | 分散 | 中 | 中 |
async/await |
高 | 集中 | 高 | 低 |
3. 使用建议
- 优先使用
async/await
替代Promise
链式调用。 - 复杂异步逻辑 使用
Promise.all
或Promise.race
优化。 - 注意
await
的串行化问题,合理选择并行或串行执行。
通过 async/await
,JavaScript 的异步编程变得更加直观和高效。掌握其核心原理和最佳实践,能够显著提升代码的可维护性和开发效率。
8️⃣ 参考 8
async/await
是 ES2017(ES8)引入的异步编程语法糖,基于 Promise 实现,让异步代码的写法更接近同步代码,极大提升了可读性和可维护性。下面详细核心概念**- async
:用于声明一个异步函数,该函数的返回值会自动包装为 Promise 对象。
await
:只能在async
函数内部使用,用于等待一个 Promise 完成,并获取其结果。
一、 async 函数1. 基本语法通过在函数声明前添加 async 关键字定义异步函数:
// 函数声明
async function fn() {}
// 函数表达式
const fn = async function() {};
// 箭头函数
const fn = async () => {};
2. 返回值特性async
函数的返回值会被自动包装为 Promise 对象:
- 若返回非 Promise 值(如数字、对象),等价于
return Promise.resolve(值)
- 若返回 Promise 对象,则直接返回该 Promise
- 若抛出错误(
throw
),等价于return Promise.reject(错误)
async function demo() {
return "hello"; // 等价于 return Promise.resolve("hello")
}
demo().then(result => console.log(result)); // 输出:hello
二、 await 关键字1. 基本用法 await 只能在 async 函数内部使用,作用是等待 Promise 完成:
- 暂停当前
async
函数的执行,直到等待的 Promise 状态变为fulfilled
或rejected
- 若 Promise 成功(
fulfilled
),await
返回其结果(resolve
的值) - 若 Promise 失败(
rejected
),await
会抛出异常(需用try/catch
捕获)
// 模拟一个异步操作
function delay(ms, value) {
return new Promise(resolve => {
setTimeout(() => resolve(value), ms);
});
}
async function asyncFunc() {
// 等待Promise完成,并获取结果
const result = await delay(1000, "异步结果");
console.log(result); // 1秒后输出:异步结果
}
asyncFunc();
2. 错误处理await
等待的 Promise 若被 reject
,会抛出异常,需通过 try/catch
捕获:
function riskyOperation() {
return new Promise((_, reject) => {
setTimeout(() => reject(new Error("操作失败")), 1000);
});
}
async function handleRisk() {
try {
const result = await riskyOperation();
console.log("成功:", result);
} catch (error) {
console.log("捕获错误:", error.message); // 输出:操作失败
}
}
handleRisk();
三、 async/await 的优势1. 解决回调地狱相比 Promise 的 then 链式调用, async/await 让代码更扁平,逻辑更清晰:
// 场景:连续执行3个依赖的异步操作
function step1() { return Promise.resolve(1); }
function step2(num) { return Promise.resolve(num * 2); }
function step3(num) { return Promise.resolve(num + 3); }
// 使用then链式调用
step1()
.then(r1 => step2(r1))
.then(r2 => step3(r2))
.then(r3 => console.log(r3)); // 输出:5
// 使用async/await(更像同步代码)
async function run() {
const r1 = await step1();
const r2 = await step2(r1);
const r3 = await step3(r2);
console.log(r3); // 输出:5
}
run();
2. 简化条件判断在异步流程中需要条件判断时,async/await
比 then
链式调用更直观:
async function checkData() {
const data = await fetchData();
// 基于异步结果的条件判断(自然直观)
if (data.isValid) {
const processed = await processData(data);
console.log(processed);
} else {
console.log("数据无效");
}
}
3. 方便调试async/await
支持传统的断点调试(then
链式调用的回调函数在调试时跳转频繁)。
四、高级用法1. 并行执行异步操作多个无依赖的异步操作,不要用串行的 await (会浪费时间),应使用 Promise.all() 并行执行:
// 低效:串行执行(总时间 = 1s + 2s = 3s)
async function serial() {
const r1 = await delay(1000, "结果1");
const r2 = await delay(2000, "结果2");
console.log(r1, r2);
}
// 高效:并行执行(总时间 = 2s,取最长的那个)
async function parallel() {
const promise1 = delay(1000, "结果1");
const promise2 = delay(2000, "结果2");
// 同时等待两个Promise完成
const [r1, r2] = await Promise.all([promise1, promise2]);
console.log(r1, r2);
}
2. 处理多个异步操作的错误使用 Promise.allSettled()
配合 await
,可以获取所有异步操作的结果(无论成功失败):
async function handleMultiple() {
const promises = [
Promise.resolve("成功1"),
Promise.reject(new Error("失败2")),
Promise.resolve("成功3")
];
// 等待所有操作完成(无论成功失败)
const results = await Promise.allSettled(promises);
// 筛选成功和失败的结果
const successes = results
.filter(r => r.status === "fulfilled")
.map(r => r.value);
const errors = results
.filter(r => r.status === "rejected")
.map(r => r.reason);
console.log("成功结果:", successes);
console.log("错误结果:", errors);
}
五、注意事项
await
只能在async
函数内部使用,否则会报错。async
函数不会阻塞主线程,await
只会暂停当前async
函数的执行。- 未用
try/catch
捕获的await
错误,会导致整个async
函数返回的 Promise 被reject
。 - 避免在循环中使用
await
(会导致串行执行),应收集所有 Promise 后用Promise.all()
处理。
总结
async/await
是 Promise 的语法糖,让异步代码更易读async
函数返回 Promise,await
等待 Promise 并获取结果- 错误处理通过
try/catch
实现,比then/catch
更符合同步代码习惯 - 配合
Promise.all()
可实现高效的并行异步操作
async/await
已成为现代 JavaScript 异步编程的首选方式,掌握它能极大提升代码质量和开发效率。
9️⃣ 参考 9
下面用「从 0 到 1」的思路,把 JavaScript 的 async / await
彻底讲透。
读完你能手写转换、能避坑、能面试。
────────────────
- 一句话定位
────────────────async / await
是 Promise 的语法糖,让异步代码看起来像同步代码,但底层仍是 Promise 的微任务队列。
────────────────
2. 基本语法
────────────────
async function foo() {
return 123; // 相当于 Promise.resolve(123)
}
// 等价于
function foo() {
return Promise.resolve(123);
}
async function bar() {
const val = await somePromise; // 等待 Promise 落定
return val * 2;
}
────────────────
3. await 的 4 条硬规则
────────────────
- 只能出现在 async 函数内部(ES2022 顶层 await 除外)。
- 右侧表达式如果不是 Promise,会被 Promise.resolve 包裹。
- 遇到
await
时,当前函数立即暂停,把后续代码注册成微任务。 - 若右侧 Promise reject,会抛出异常(需 try/catch 或 .catch)。
────────────────
4. 执行顺序(微任务视角)
────────────────
console.log(1);
async function f() {
console.log(2);
await Promise.resolve();
console.log(3); // 微任务阶段才执行
}
f();
console.log(4);
// 输出:1 2 4 3
────────────────
5. 错误处理
────────────────
async function load() {
try {
const u = await fetch('/user');
const j = await u.json();
return j;
} catch (e) {
console.error('网络或 JSON 错误', e);
}
}
try/catch
能捕获:
- await 后的 Promise reject
- await 前抛出的同步异常
- 任何
throw
────────────────
6. 与 Promise 链等价转换
────────────────
// Promise 链
fetch('/user')
.then(r => r.json())
.then(j => console.log(j))
.catch(console.error);
// async/await
async function show() {
try {
const r = await fetch('/user');
const j = await r.json();
console.log(j);
} catch (e) {
console.error(e);
}
}
────────────────
7. 并发 vs 串行
────────────────
串行(慢):
const a = await delay(1000);
const b = await delay(1000);
并发(快):
const [a, b] = await Promise.all([delay(1000), delay(1000)]);
────────────────
8. async 函数总是返回 Promise
────────────────
async function f() { return 1; }
f().then(console.log); // 1
即使写了 return 非 Promise
,也会被 Promise.resolve()
包裹。
────────────────
9. 常见坑 & 面试题
────────────────
-
忘记 await
const data = fetch(url)
拿到的是 Promise 不是结果。 -
在循环里串行 await
for (const id of ids) await fetch(id); // 串行 await Promise.all(ids.map(fetch)); // 并行
-
顶层 await
ES2022 起模块顶层可直接写await
,但仍受微任务调度影响。 -
手写 Promise → async 转换
面试常考:把任何.then
链改写成 async/await 并保证错误等价。
────────────────
10. 速查小抄
────────────────
代码片段 | 结果/行为 |
---|---|
async () => 1 |
返回 Promise<1> |
await 123 |
立即得到 123(被 Promise.resolve) |
await Promise.reject('err') |
抛异常,需 try/catch |
async () => { throw 'err' } |
返回 Promise<rejected> |
────────────────
一句话总结
────────────────async
把函数变成“自动 Promise 生成器”,await
把 Promise 的 resolve/reject 变成 同步语法;
其余所有规则(微任务、错误、并发)与 Promise 完全一致。
🔟 参考 10
JavaScript async/await 详解
一、基本概念
async/await 是 ES2017 引入的异步编程解决方案,基于 Promise 的语法糖,使异步代码具有同步代码的可读性。
核心特点:
async
声明异步函数,始终返回 Promise 对象async function fetchData() { return "data"; // 等价于 Promise.resolve("data") }
await
暂停异步函数执行,等待 Promise 完成async function getUser() { const response = await fetch('/api/user'); // 等待请求完成 return response.json(); }
二、工作原理
-
执行流程:
- 遇到
await
时暂停函数执行,将控制权交还事件循环 - 等待 Promise 完成后恢复函数执行
- 不会阻塞主线程(非 CPU 阻塞)
- 遇到
-
错误处理:
async function fetchWithRetry() { try { const data = await fetchData(); } catch (error) { console.error("请求失败:", error); } }
-
返回值转换:
返回值类型 转换结果 非 Promise 值 Promise.resolve(value)
Promise 对象 直接返回该 Promise 抛出错误 Promise.reject(error)
三、关键特性
-
执行顺序示例:
console.log("Start"); async function demo() { console.log("Async start"); await new Promise(r => setTimeout(r, 1000)); console.log("Async end"); } demo(); console.log("End"); // 输出顺序: // Start → Async start → End → (1秒后) Async end
-
并行执行优化:
// 顺序执行 (慢) const user = await fetchUser(); const posts = await fetchPosts(); // 并行执行 (快) const [user, posts] = await Promise.all([ fetchUser(), fetchPosts() ]);
-
顶层 await (ES2022):
// 模块中直接使用 const data = await fetchConfig(); export default data;
四、使用场景
- 顺序异步操作(如 API 链式调用)
- 错误处理复杂的异步流程
- 替代 Promise 链式调用:
// Promise 版本 fetchData() .then(process) .then(save) .catch(handleError); // async/await 版本 try { const data = await fetchData(); const processed = await process(data); await save(processed); } catch (err) { handleError(err); }
五、注意事项
-
避免阻塞陷阱:
// 错误示例 (意外阻塞) async function processBatch() { items.forEach(async item => { await processItem(item); // 不会并行执行 }); } // 正确做法 async function processBatch() { await Promise.all(items.map(processItem)); }
-
浏览器兼容性:
- 现代浏览器和 Node.js 12+ 完全支持
- 旧环境需通过 Babel 转译
-
性能影响:
- 比原生 Promise 稍慢(约 10%)
- 可读性优势通常大于性能差异
async/await 让异步代码获得同步代码的可读性,同时保持非阻塞特性,是现代 JavaScript 异步编程的首选方案。
🤔 参考 11
JavaScript 的 async / await 详解
一、核心概念与语法
-
async
函数- 定义:通过
async function
声明,隐式返回一个 Promise 对象。 - 返回值:
- 若返回普通值 → Promise 以该值
fulfilled
。 - 若抛出异常 → Promise 以错误
rejected
。
- 若返回普通值 → Promise 以该值
async function fetchData() { return "数据"; } // 等价于: function fetchData() { return Promise.resolve("数据"); }
- 定义:通过
-
await
关键字- 作用:暂停
async
函数的执行,等待 Promise 完成并返回结果。 - 限制:只能在
async
函数或模块顶级作用域中使用。 - 返回值:
- Promise 成功 → 返回解析值。
- Promise 失败 → 抛出异常,需通过
try...catch
捕获。
async function getData() { const data = await fetch("https://api.example.com/data"); return data.json(); }
- 作用:暂停
二、执行流程与底层机制
-
同步代码风格
async
/await
使异步代码结构接近同步代码,提升可读性。例如:async function sequential() { const data1 = await step1(); // 等待 step1 完成 const data2 = await step2(data1); // 等待 step2 完成 return data2; }
-
事件循环与微任务
await
后的代码会被包装为 微任务(Microtask),在 Promise 解决后执行。- 示例:
console.log("Start"); async function test() { console.log("Async 开始"); await new Promise(resolve => setTimeout(resolve, 100)); console.log("Async 结束"); } test(); console.log("End"); // 输出顺序:Start → Async 开始 → End → Async 结束
-
Promise 的等效转换
// 原始 Promise 链式调用 fetchData() .then(data => processData(data)) .catch(error => handleError(error)); // async/await 改写 async function handle() { try { const data = await fetchData(); const result = await processData(data); return result; } catch (error) { handleError(error); } }
三、错误处理
-
try...catch
捕获- 在
async
函数内使用try...catch
捕获await
的异常。
async function fetchData() { try { const response = await fetch("https://api.example.com/data"); if (!response.ok) throw new Error("HTTP错误"); return response.json(); } catch (error) { console.error("请求失败:", error); return null; } }
- 在
-
外部
.catch()
处理- 调用
async
函数时,通过.catch()
捕获返回的 Promise 错误。
fetchData() .then(data => console.log(data)) .catch(error => console.error(error));
- 调用
-
未捕获的 Promise 拒绝
- 若未处理错误,会导致
UnhandledPromiseRejectionWarning
。 - 解决方法:全局监听
unhandledrejection
事件(浏览器)或process.on('unhandledRejection')
(Node.js)。
- 若未处理错误,会导致
四、高级用法
-
并行执行异步操作
- 使用
Promise.all
结合await
实现并行:
async function fetchMultiple() { try { const [user, posts] = await Promise.all([fetchUser(), fetchPosts()]); return { user, posts }; } catch (error) { console.error("请求失败:", error); } }
- 使用
-
链式调用与值传递
- 每个
await
的返回值作为下一个异步操作的输入:
async function processData() { const rawData = await fetchRawData(); const parsedData = await parseData(rawData); return savedData(parsedData); }
- 每个
-
返回 Promise 的函数
await
可等待任何返回 Promise 的表达式,包括普通函数:
function delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } async function example() { await delay(1000); // 等待 1 秒 console.log("延迟执行"); }
五、与 Promise 的对比
特性 | Promise | async/await |
---|---|---|
语法 | 链式调用 .then().catch() |
同步代码风格,使用 try...catch |
错误处理 | 需在 .catch() 中集中处理 |
通过 try...catch 捕获更直观 |
调试 | 堆栈信息复杂,难以定位 | 错误位置明确,调试更简单 |
并行处理 | 需手动使用 Promise.all() |
结合 Promise.all() 更简洁 |
六、实际应用场景
-
网络请求
async function getUserData(userId) { try { const response = await fetch(`/api/users/${userId}`); if (!response.ok) throw new Error("用户不存在"); return response.json(); } catch (error) { console.error("请求失败:", error); return null; } }
-
文件读写(Node.js)
const fs = require('fs').promises; async function readFileContent(path) { try { const data = await fs.readFile(path, 'utf-8'); return data; } catch (error) { console.error("读取文件失败:", error); } }
-
数据库操作
async function getUserById(userId) { try { const client = await MongoClient.connect(uri); const db = client.db("mydb"); const user = await db.collection("users").findOne({ _id: userId }); client.close(); return user; } catch (error) { console.error("数据库错误:", error); } }
七、注意事项与最佳实践
-
避免过度使用
await
- 顺序执行异步操作会降低性能,尽量使用
Promise.all
并行处理。
// 不推荐:顺序执行 await step1(); await step2(); // 推荐:并行执行 await Promise.all([step1(), step2()]);
- 顺序执行异步操作会降低性能,尽量使用
-
错误处理策略
- 在关键路径使用
try...catch
,非关键路径允许错误冒泡。 - 提供默认值或降级方案:
async function fetchData() { try { const data = await fetch("/api/data"); return data.json(); } catch (error) { return { data: "默认值" }; // 降级处理 } }
- 在关键路径使用
-
调试技巧
- 使用
console.log
或调试工具追踪异步流程。 - 注意
await
后的微任务调度,避免逻辑错乱。
- 使用
八、底层原理
-
生成器与协程
async
/await
基于生成器的暂停-恢复机制,通过协程管理异步流程。- 生成器函数通过
yield
暂停执行,async
函数通过await
实现类似效果。
-
Promise 的封装
async
函数返回的 Promise 由函数体内部的return
或抛出异常决定状态。await
表达式会创建一个新的 Promise,并在原 Promise 解决后恢复执行。
总结
async
/await
的核心价值:将异步代码转换为同步风格,提升可读性和维护性。- 错误处理:优先使用
try...catch
集中式捕获,结合.catch()
实现链式处理。 - 性能优化:合理使用
Promise.all
减少等待时间,避免阻塞主线程。
通过掌握 async
/await
的机制,可以更高效地编写非阻塞的异步代码,尤其适用于复杂的前后端交互场景。
🤔 参考 12
在 JavaScript 中,async/await
是处理异步操作的革命性语法,它能让你用写同步代码的方式处理异步逻辑。以下是从底层原理到实际应用的全方位解析:
一、核心机制
1. async 关键字
- 作用:声明一个异步函数
- 强制返回值:总是返回 Promise 对象
async function basic() {
return 42; // 等价于 return Promise.resolve(42)
}
// 执行结果
basic().then(console.log); // 输出 42
2. await 关键字
- 作用域:只能在
async
函数内部使用 - 暂停执行:直到右侧的 Promise 进入决断状态
async function fetchData() {
const response = await fetch('/api'); // 等待请求完成
const data = await response.json(); // 等待数据解析
return data;
}
二、与传统 Promise 链的对比
案例:多步骤异步操作
// 传统 Promise 链式写法
function oldWay() {
return fetchData()
.then(validate)
.then(process)
.catch(handleError);
}
// async/await 写法
async function newWay() {
try {
const raw = await fetchData();
const valid = await validate(raw);
return process(valid);
} catch (err) {
handleError(err);
}
}
对比优势:
- 线性代码结构:消除回调嵌套
- 同步错误处理:使用
try/catch
替代.catch()
- 调试友好:调试器能正确追踪调用栈
三、执行控制策略
1. 并行加速技巧
// 顺序执行(总耗时 = 各任务耗时之和)
async function serial() {
const a = await task(100);
const b = await task(200);
return a + b; // 总耗时 300ms
}
// 并行执行(总耗时 ≈ 最慢任务耗时)
async function parallel() {
const [a, b] = await Promise.all([task(100), task(200)]);
return a + b; // 总耗时 200ms
}
2. 循环中的注意事项
// 错误示范:意外串行执行
async function wrongLoop() {
const arr = [100, 200, 300];
arr.forEach(async (time) => { // ❌ forEach 不会等待
await delay(time);
});
}
// 正确做法:显式控制循环
async function correctLoop() {
const arr = [100, 200, 300];
for (const time of arr) { // ✅ 等待每次迭代
await delay(time);
}
}
四、错误处理模式
1. 基本错误捕获
async function safeFetch() {
try {
const res = await fetch('...');
return await res.json();
} catch (err) {
console.error('请求失败:', err);
throw new Error('降级数据'); // 继续向上抛出
}
}
2. 高阶错误处理封装
// 封装可复用的错误处理器
function withRetry(asyncFunc, retries = 3) {
return async (...args) => {
for (let i = 0; i < retries; i++) {
try {
return await asyncFunc(...args);
} catch (err) {
if (i === retries - 1) throw err;
await delay(1000 * (i + 1));
}
}
};
}
// 使用示例
const reliableFetch = withRetry(fetch);
五、底层原理透析
1. 生成器模拟实现async/await
本质上是生成器(Generator)的语法糖:
function _async(fn) {
return function () {
const gen = fn.apply(this, arguments);
return new Promise((resolve, reject) => {
function step(key, arg) {
let result;
try {
result = gen[key](arg);
} catch (err) {
return reject(err);
}
const { value, done } = result;
if (done) return resolve(value);
return Promise.resolve(value).then(
val => step("next", val),
err => step("throw", err)
);
}
step("next");
});
};
}
2. 事件循环中的执行顺序
console.log('同步开始');
(async () => {
console.log('async内部-前');
await Promise.resolve();
console.log('async内部-后'); // 进入微任务队列
})();
console.log('同步结束');
/* 输出顺序:
同步开始
async内部-前
同步结束
async内部-后 */
六、性能优化策略
- 避免不必要的 await
// ❌ 错误
const data = await getData();
return process(data);
// ✅ 正确
return getData().then(process); // 减少一次微任务
- 合理利用缓存
const cache = new Map();
async function getCachedData(id) {
if (cache.has(id)) return cache.get(id);
const data = await fetchData(id);
cache.set(id, data);
return data;
}
七、浏览器兼容方案
对于不支持 async/await
的老旧浏览器:
- 使用 Babel 进行代码转译
- 搭配 regenerator-runtime
- 打包时自动注入 polyfill
掌握 async/await
后,你可以:
- 提升代码可维护性 40% 以上
- 降低异步代码错误率约 35%
- 轻松处理复杂异步流程控制
🤔 参考 13
以下是针对 JavaScript 中 async
和 await
的超详细解析,涵盖核心机制、语法糖、典型场景及最佳实践:
🔑 一、核心概念速览
关键词 | 作用 | 本质 |
---|---|---|
async |
声明一个异步函数,使其返回一个 Promise | 函数修饰符 |
await |
暂停函数执行,等待右侧 Promise 的决议结果(fulfilled/rejected) | 运算符(仅可在 async 函数内使用) |
🧠 二、深度解析与关键规则
✅ 1. async 函数的特性
🔹 基础行为
- 始终返回 Promise:无论是否显式使用
return
,async
函数都会隐式返回一个 Promise。- 若函数内有
return x
,则等同于Promise.resolve(x)
。 - 若无
return
,则返回Promise.resolve(undefined)
。
- 若函数内有
- 错误自动捕获:若函数内部抛出异常,返回的 Promise 会被拒绝(
rejected
),原因为该异常。
🌰 示例:
async function fetchData() {
return "数据"; // 等同于 Promise.resolve("数据")
}
fetchData().then(data => console.log(data)); // 输出 "数据"
async function throwError() {
throw new Error("出错了");
}
throwError().catch(err => console.error(err)); // 输出 Error: 出错了
✅ 2. await 运算符的规则
🔹 核心机制
- 暂停执行:
await
会暂停所在async
函数的执行,直到右侧表达式是一个 Promise 且状态变为fulfilled
或rejected
。 - 值传递:若 Promise 成功(
fulfilled
),await
返回其解析值;若失败(rejected
),抛出异常。 - 非阻塞事件循环:暂停期间释放事件循环,允许其他任务运行。
⚠️ 重要限制:
- 仅能在
async
函数内使用:在普通函数或全局作用域中使用await
会导致语法错误。 - 右侧必须是 Promise:若右侧是普通值(如字符串、数字),会被自动包装为
Promise.resolve()
。
🌰 基础示例:
async function main() {
const result = await Promise.resolve("成功"); // 等待 Promise 解析
console.log(result); // 输出 "成功"
try {
const errorResult = await Promise.reject(new Error("失败")); // 抛出异常
} catch (err) {
console.error(err); // 输出 Error: 失败
}
}
main();
⚙️ 三、实战场景与技巧
👨💻 场景 1:替代 .then() 链式调用
传统 Promise 风格:
fetch("/api/user")
.then(response => response.json())
.then(user => updateUI(user))
.catch(error => showError(error));
async/await 风格:
async function loadUser() {
try {
const response = await fetch("/api/user"); // 等待请求完成
const user = await response.json(); // 等待 JSON 解析
updateUI(user); // 更新界面
} catch (error) {
showError(error); // 统一错误处理
}
}
loadUser();
🛠️ 场景 2:顺序执行多个异步操作
async function processOrder() {
const paymentStatus = await processPayment(); // 等待支付完成
const shippingLabel = await generateShippingLabel(paymentStatus); // 根据支付结果生成运单
const trackingNumber = await sendPackage(shippingLabel); // 发送包裹并获取物流单号
return trackingNumber;
}
🚀 场景 3:并行执行异步任务
async function parallelTasks() {
const [user, posts] = await Promise.all([
fetchUser(), // 同时发起两个请求
fetchPosts()
]);
console.log(`用户 ${user.name} 的文章数: ${posts.length}`);
}
🔍 场景 4:条件控制流
async function checkAuth() {
const token = localStorage.getItem("token");
if (!token) throw new Error("未登录");
const user = await validateToken(token); // 验证令牌有效性
return user;
}
❗ 四、常见误区与解决方案
❌ 误区 1:忽略 async 函数的返回值
// 错误写法:未处理 Promise 导致无法获取结果
async function getData() {
return fetch("/api/data").then(res => res.json());
}
getData(); // 无任何效果
// 正确写法:消费返回的 Promise
getData().then(data => console.log(data));
❌ 误区 2:在全局作用域中使用 await
// 语法错误!await 只能在 async 函数内使用
let data = await fetch("/api/data"); // Uncaught SyntaxError
❌ 误区 3:混淆同步与异步行为
async function printNum() {
console.log(1);
await console.log(2); // 宏任务队列化
console.log(3); // 微任务队列优先执行
}
printNum();
// 输出顺序:1 → 2 → 3(看似同步,实则异步)
❌ 误区 4:忘记错误处理
// 危险!未捕获的异常会导致未处理的 Promise 拒绝
async function riskyOperation() {
const data = await fetch("/api/risky"); // 假设请求失败
return data.json(); // 不会执行到这里
}
// 正确写法:使用 try...catch
async function safeOperation() {
try {
const data = await fetch("/api/safe");
return await data.json();
} catch (error) {
console.error("操作失败:", error);
throw error; // 根据需求决定是否重新抛出
}
}
💎 五、最佳实践指南
- 统一错误处理:始终使用
try...catch
包裹await
调用,避免未捕获异常。 - 合理拆分函数:将复杂逻辑拆分为小的
async
函数,提升可测试性和复用性。 - 避免过度嵌套:对于多层嵌套的
await
,考虑提取中间变量或使用辅助函数。 - 性能优化:对于频繁触发的操作(如滚动事件),结合防抖(debounce)或节流(throttle)技术。
- 类型校验:在
await
后添加类型检查,防止意外的类型转换。
📚 六、关联知识扩展
概念 | 说明 |
---|---|
Promise.all() |
等待所有 Promise 完成,任一失败即拒绝 |
Promise.race() |
竞争第一个完成的 Promise,快照决 |
Promise.allSettled() |
等待所有 Promise 结算(无论成功/失败),返回包含状态的对象数组 |
for...await...of |
遍历异步可迭代对象(如异步生成器) |
总结:async/await
通过同步风格的语法大幅降低了异步代码的复杂度,使代码更易读、更易维护。关键在于理解其底层仍基于 Promise,并遵循错误处理的最佳实践。
🤔 参考 14
async
和 await
是 JavaScript 中用于处理异步操作的一种语法,使得异步代码更像同步代码,提升了可读性和可维护性。
一、async 函数
async
是一个关键字,用于声明一个函数是异步函数。- 异步函数会自动返回一个 Promise。
- 即使函数没有显式返回 Promise,
async
函数也会将返回值包装成一个已解决(resolved)的 Promise。
示例:
async function sayHello() {
return "Hello";
}
sayHello().then(message => console.log(message)); // 输出 "Hello"
二、await 关键字
await
只能在async
函数内部使用。- 它会暂停 async 函数的执行,等待 Promise 完成(即 resolved 或 rejected)。
- 如果 Promise 成功完成,
await
返回其结果;如果失败,会抛出异常。
示例:
async function fetchUser() {
let response = await fetch('https://api.example.com/user/1');
let data = await response.json();
console.log(data);
}
三、错误处理
可以使用 try...catch
来捕获 await
中的异常:
async function fetchUser() {
try {
let response = await fetch('https://api.example.com/user/1');
if (!response.ok) throw new Error("Network response was not ok");
let data = await response.json();
console.log(data);
} catch (error) {
console.error("Error fetching user:", error);
}
}
四、async/await 的优势
- 代码更清晰,避免了“回调地狱”(callback hell)。
- 更容易调试和测试。
- 更接近同步代码的逻辑结构,便于理解和维护。
五、注意事项
await
只能在async
函数中使用。- 多个异步任务如果互不依赖,可以使用
Promise.all()
来并行执行,提升性能。
示例:并行执行多个异步任务
async function fetchData() {
let [userRes, postRes] = await Promise.all([
fetch('https://api.example.com/user/1'),
fetch('https://api.example.com/posts')
]);
let user = await userRes.json();
let posts = await postRes.json();
console.log(user, posts);
}
总结
async
函数返回 Promise。await
等待 Promise 完成。- 使用
try...catch
捕获错误。 - 适合处理异步操作,如网络请求、文件读写等。
如果你还有具体的问题或想了解更高级的用法,欢迎继续提问!
🤔 参考 15
async/await
是 JavaScript 处理异步操作的语法糖,基于 Promise 实现,旨在让异步代码的书写和阅读更接近同步代码。以下是详细解析:
1. async 函数
- 作用:声明一个异步函数
- 返回值:总是返回一个 Promise 对象
- 函数内返回普通值 → 自动包装为 resolved Promise
- 函数内抛出错误 → 返回 rejected Promise
- 函数内返回 Promise → 直接返回该 Promise
async function foo() {
return 42; // 等价于 Promise.resolve(42)
}
foo().then(console.log); // 42
async function bar() {
throw new Error("失败"); // 等价于 Promise.reject(error)
}
bar().catch(console.error); // Error: 失败
2. await 关键字
- 作用:暂停异步函数执行,等待 Promise 完成
- 特性:
- 只能在
async
函数内部使用 - 等待 Promise 状态变为 resolved 后继续执行
- 返回 Promise 的解决值
- 遇到 rejected Promise 会抛出异常(可用 try/catch 捕获)
- 只能在
async function demo() {
const result = await new Promise(resolve =>
setTimeout(() => resolve("完成"), 1000)
);
console.log(result); // 1秒后输出"完成"
try {
await Promise.reject("出错了");
} catch (err) {
console.error(err); // "出错了"
}
}
3. 错误处理
- 推荐方式:
try/catch
- 替代方式:在 Promise 后添加
.catch()
// 方式1: try/catch
async function fetchData() {
try {
const data = await fetchApi();
} catch (error) {
console.error("请求失败", error);
}
}
// 方式2: catch处理
fetchApi()
.then(data => {...})
.catch(error => console.error(error));
4. 执行流程控制
顺序执行(一个接一个)
async function sequential() {
const r1 = await task1();
const r2 = await task2(); // 等待task1完成
}
并行执行(同时触发)
async function parallel() {
const [res1, res2] = await Promise.all([task1(), task2()]);
// 或
const p1 = task1(); // 立即启动
const p2 = task2(); // 立即启动
await p1;
await p2;
}
5. 关键特性
- 非阻塞性:
await
暂停的是当前async
函数,不影响主线程 - 隐式转换:
await
会将非 Promise 值转换为 resolved Promiseconst num = await 100; // 等价于 await Promise.resolve(100)
- 栈追踪:比传统 Promise 链有更清晰的错误堆栈
6. 常见误区
错误:在循环中误用顺序执行
// ❌ 低效写法(顺序等待)
for (const url of urls) {
const res = await fetch(url); // 每次循环等待完成
}
// ✅ 高效并行写法
const promises = urls.map(url => fetch(url));
const results = await Promise.all(promises);
错误:忘记 await
async function saveData() {
const data = fetchData(); // ❌ 忘记await,data是Promise对象
console.log(data); // 输出 Promise { <pending> }
}
7. 浏览器兼容性
- 支持所有现代浏览器(Chrome 55+、Firefox 52+、Safari 10.1+)
- Node.js 7.6+ 原生支持
- 旧环境可通过 Babel 转译
总结对比
模式 | 优点 | 缺点 |
---|---|---|
async/await | 代码线性易读,错误处理直观 | 必须包裹在 async 函数中 |
Promise链 | 无需函数包裹,适合简单场景 | 链式嵌套复杂时难以阅读 |
回调函数 | 兼容性最好 | 回调地狱,错误处理困难 |
最佳实践:
在复杂异步逻辑中优先使用
async/await
+try/catch
,结合Promise.all()
处理并行任务,可使代码既简洁又可维护。
🤔 参考 16
JavaScript 的 async 与 await 详解
核心概念:async/await 的本质
async/await
是 JavaScript 处理异步操作的语法糖,它基于 Promise,但提供了更直观、同步风格的代码结构:
// 传统 Promise
fetchData()
.then(data => processData(data))
.then(result => displayResult(result))
.catch(error => handleError(error));
// async/await 实现
async function fetchAndDisplay() {
try {
const data = await fetchData();
const result = await processData(data);
displayResult(result);
} catch (error) {
handleError(error);
}
}
一、async 函数详解
1. 基本特性
- 声明方式:在函数前添加
async
关键字 - 返回值:始终返回 Promise 对象
- 返回非 Promise 值 → 自动包装为 resolved Promise
- 抛出错误 → 返回 rejected Promise
- 返回 Promise → 直接返回该 Promise
async function example() {
return 42; // 等价于 Promise.resolve(42)
}
async function fail() {
throw new Error("Oops"); // 等价于 Promise.reject(Error)
}
example().then(console.log); // 42
fail().catch(console.error); // Error: Oops
2. 执行流程特点
- 同步执行直到遇到第一个
await
- 遇到
await
暂停执行,交出控制权 - 当等待的 Promise 解决后恢复执行
console.log("Start");
async function demo() {
console.log("Before await");
await new Promise(res => setTimeout(res, 1000));
console.log("After await");
}
demo();
console.log("End");
/* 输出顺序:
Start
Before await
End
(等待1秒)
After await
*/
二、await 表达式详解
1. 基本用法
- 只能在 async 函数内部使用
- 暂停代码执行,等待 Promise 解决
- 返回 Promise 的解决值
async function getData() {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
return data;
}
2. 等待行为分析
等待对象类型 | await 行为 |
---|---|
Promise | 等待解决/拒绝 |
非 Promise | 直接返回值 |
thenable 对象 | 等待其 then 方法解决 |
抛出错误 | 触发 catch 块 |
// 等待非 Promise 值
const value = await 42; // value = 42
// 等待 thenable 对象
const thenable = {
then(resolve) {
setTimeout(() => resolve('Done'), 1000);
}
};
console.log(await thenable); // 1秒后输出 "Done"
三、错误处理机制
1. try/catch 模式(推荐)
async function loadResource() {
try {
const response = await fetch('/resource');
if (!response.ok) {
throw new Error('Network response was not OK');
}
return await response.json();
} catch (error) {
console.error('加载失败:', error);
return { data: [] }; // 返回默认值
}
}
2. 结合 catch() 方法
async function process() {
const data = await fetchData().catch(handleError);
if (!data) return; // 错误处理后的判断
// 正常处理逻辑
}
四、高级使用技巧
1. 并行执行优化
// 顺序执行(慢)
async function sequentialFetch() {
const user = await fetch('/user');
const posts = await fetch('/posts');
return { user, posts };
}
// 并行执行(快)
async function parallelFetch() {
const [user, posts] = await Promise.all([
fetch('/user'),
fetch('/posts')
]);
return { user, posts };
}
2. 循环中的 await
// 顺序处理(每个操作等待前一个完成)
async function processArray(array) {
for (const item of array) {
await processItem(item);
}
}
// 并行处理(所有操作同时开始)
async function processArrayParallel(array) {
await Promise.all(array.map(item => processItem(item)));
}
3. 立即执行 async 函数
// IIFE 模式
(async () => {
const data = await fetchData();
console.log(data);
})();
// 顶层 await(ES2022+,仅模块中可用)
// 在模块顶层直接使用
const data = await fetchData();
console.log(data);
五、常见问题与解决方案
1. 忘记 await
// 错误:返回 Promise 而不是实际值
async function getValue() {
const promise = fetchData(); // 缺少 await!
return promise.result; // undefined
}
// 正确
async function getValue() {
const data = await fetchData();
return data.result;
}
2. 异常传播
async function task1() {
await task2(); // task2 的异常会传播到这里
}
async function task2() {
throw new Error('Task2 failed');
}
task1().catch(e => console.log(e.message)); // 输出: "Task2 failed"
3. 性能优化
// 优化前:不必要的顺序等待
async function unoptimized() {
const a = await getA(); // 等待A
const b = await getB(); // 等待B(不依赖A)
return a + b;
}
// 优化后:并行请求
async function optimized() {
const [a, b] = await Promise.all([
getA(),
getB() // 同时请求
]);
return a + b;
}
六、与 Promise 的对比
特性 | Promise | async/await |
---|---|---|
代码结构 | 链式调用 | 同步风格 |
错误处理 | .catch() 方法 | try/catch 语句 |
可读性 | 回调嵌套可能复杂 | 线性流程更清晰 |
调试 | 断点跳转困难 | 可逐行调试 |
返回值 | 必须返回 Promise | 自动包装为 Promise |
流程控制 | 需要手动链式调用 | 自动暂停/恢复执行上下文 |
七、最佳实践指南
-
优先使用 try/catch:处理异步错误
async function safeOperation() { try { return await riskyOperation(); } catch (error) { // 错误处理逻辑 } }
-
并行独立操作:使用
Promise.all
async function loadDashboard() { const [user, settings, notifications] = await Promise.all([ fetchUser(), fetchSettings(), fetchNotifications() ]); // 渲染所有数据 }
-
避免过度顺序化:
// 不好:不必要的顺序执行 const a = await getA(); const b = await getB(); // 不依赖A,应该并行 // 好:独立操作并行执行 const [a, b] = await Promise.all([getA(), getB()]);
-
合理处理并发:
// 限制并发数 import pLimit from 'p-limit'; const limit = pLimit(3); // 最大并发数 async function processItems(items) { const promises = items.map(item => limit(() => processItem(item)) ); return Promise.all(promises); }
八、浏览器与运行环境支持
环境 | 支持版本 |
---|---|
Chrome | 55+ (2016) |
Firefox | 52+ (2017) |
Safari | 10.1+ (2017) |
Edge | 15+ (2017) |
Node.js | 7.6+ (需要 flag) |
8.10+ (正式支持) | |
TypeScript | 1.7+ (编译到 ES3/ES5) |
总结:async/await 的价值
- 代码可读性:将异步代码写成同步形式
- 错误处理简化:使用 try/catch 统一处理
- 调试友好:支持标准调试流程
- 逻辑清晰:避免回调地狱和复杂链式调用
- 与现代JS整合:与 Promise、迭代器等无缝协作
// 完整示例:API请求处理
async function fetchUserData(userId) {
try {
const response = await fetch(`/api/users/${userId}`);
if (!response.ok) throw new Error('API响应错误');
const user = await response.json();
const [orders, messages] = await Promise.all([
fetchUserOrders(user.id),
fetchUserMessages(user.id)
]);
return { ...user, orders, messages };
} catch (error) {
console.error('获取用户数据失败:', error);
return null;
} finally {
console.log('用户数据请求完成');
}
}
掌握 async/await 可以显著提升异步代码的质量和开发效率,是现代 JavaScript 开发的必备技能。
🤔 参考 17
在 JavaScript 中,async/await
是处理异步操作的语法糖,它基于 Promise,但让异步代码的书写和阅读更接近同步方式。下面从核心概念到实际使用进行详细解析:
一、核心概念
-
async
函数- 声明方式:在函数前加
async
关键字 - 始终返回 Promise 对象:
- 函数内返回非 Promise 值 → 自动包装为 resolved Promise
- 抛出错误 → 返回 rejected Promise
async function foo() { return 42; // 等价于 Promise.resolve(42) } foo().then(console.log); // 输出 42
- 声明方式:在函数前加
-
await
表达式- 只能在
async
函数内部使用 - 暂停函数执行,等待 Promise 状态变更:
- Promise 成功 → 返回
resolve
的值 - Promise 失败 → 抛出异常(可用
try/catch
捕获)
- Promise 成功 → 返回
async function bar() { const result = await somePromise; // 等待 Promise 完成 console.log(result); }
- 只能在
二、执行流程解析
async function example() {
console.log("A");
await delay(1000); // 暂停执行(不阻塞主线程)
console.log("B");
}
- 执行
console.log("A")
- 遇到
await
:- 暂停
example
函数执行 - 执行
delay(1000)
异步操作 - 将函数剩余部分放入微任务队列
- 暂停
- 主线程继续执行其他代码
- 1秒后异步操作完成,恢复函数执行,输出
"B"
三、错误处理
使用 try/catch
捕获异常:
async function fetchData() {
try {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
return data;
} catch (error) {
console.error("请求失败:", error);
throw error; // 可选择继续抛出错误
}
}
四、关键特性
-
并行优化
使用Promise.all()
避免串行等待:async function parallelFetch() { const [user, posts] = await Promise.all([ fetch('/user'), fetch('/posts') ]); // 两个请求并行发送 }
-
顶层
await
(ES2022)
在模块顶层直接使用:// 模块中 const data = await fetchData(); console.log("模块加载完成即获取数据");
-
非阻塞原理
await
只是语法暂停点,实际通过事件循环机制:console.log("Start"); asyncFunc(); // 内含 await console.log("End"); // 输出顺序:Start → End → 异步操作结果
五、与传统 Promise 对比
// Promise 链式调用
function promiseVersion() {
fetchData()
.then(data => process(data))
.then(result => save(result))
.catch(handleError);
}
// async/await 版本
async function asyncVersion() {
try {
const data = await fetchData();
const result = await process(data);
await save(result);
} catch (err) {
handleError(err);
}
}
优势:代码扁平化,避免回调地狱,错误处理更集中。
六、注意事项
-
避免过度串行
不必要的顺序等待会降低性能:// ❌ 低效写法 const a = await getA(); // 先等A完成 const b = await getB(); // 再等B完成 // ✅ 高效并行 const [a, b] = await Promise.all([getA(), getB()]);
-
循环中的
await
在循环内使用需谨慎:// 顺序执行(可能低效) for (const url of urls) { await fetch(url); // 逐个请求 } // 并行执行 const promises = urls.map(url => fetch(url)); await Promise.all(promises);
-
兼容性
支持所有现代浏览器(IE 除外)和 Node.js 7.6+,可通过 Babel 转译支持旧环境。
七、总结
特性 | 说明 |
---|---|
async 函数 |
声明异步函数,隐式返回 Promise |
await |
暂停函数执行,等待 Promise 结果 |
错误处理 | 使用 try/catch 替代 .catch() |
并行优化 | 结合 Promise.all() 提升性能 |
执行机制 | 基于事件循环,通过微任务队列恢复执行 |
最佳实践:
- 用
async/await
替代复杂 Promise 链 - 并行操作优先使用
Promise.all()
- 始终用
try/catch
处理错误 - 避免在循环中滥用顺序等待
🤔 参考 18
JavaScript 的 async 与 await 深度解析
async/await
是 ES2017 引入的异步编程革命性特性,基于 Promise 但提供了更直观的同步代码风格。以下是全面解析:
一、核心概念
-
async
函数:- 声明异步函数:
async function foo() {}
或const bar = async () => {}
- 总是返回 Promise:
async function test() { return 42; } test() instanceof Promise; // true
- 声明异步函数:
-
await
表达式:- 暂停异步函数执行,等待 Promise 完成
- 只能用在
async
函数内部
async function fetchData() { const data = await fetch('/api'); // 等待 Promise 解决 return data.json(); }
二、执行机制详解
async function example() {
console.log("1. 同步代码");
const result = await new Promise(res =>
setTimeout(() => res("2. 异步结果"), 1000)
);
console.log(result);
return "3. 完成";
}
console.log("0. 调用前");
example().then(console.log);
console.log("0.5 调用后");
/* 输出顺序:
0. 调用前
1. 同步代码
0.5 调用后
2. 异步结果
3. 完成
*/
关键行为:
async
函数同步执行直到遇到await
await
让出线程,函数外代码继续执行- Promise 解决后,函数恢复执行
- 返回值自动包装为 Promise
三、错误处理
方式 1: try/catch (推荐)
async function loadResource() {
try {
const data = await fetch('/api');
return process(data);
} catch (error) {
console.error("请求失败:", error);
return getFallbackData(); // 恢复执行
}
}
方式 2:Promise 的 .catch()
asyncFunc()
.then(handleSuccess)
.catch(handleError); // 捕获 async 函数内的错误
注意:
await
会抛出被拒绝 Promise 的错误- 未捕获错误会导致返回的 Promise 拒绝
四、与 Promise 的互操作性
-
async
函数 ⇄ Promise 无缝转换// Promise → async const data = await promise; // async → Promise asyncFunc().then(...);
-
混合使用示例
async function getUserPosts(userId) { // 等待 Promise const user = await fetchUser(userId); // 返回 Promise 给调用者 return fetchPosts(user.id); }
五、并行执行优化
1. 顺序执行(慢)
// ❌ 顺序执行(总耗时 = 各请求之和)
const user = await fetchUser();
const posts = await fetchPosts(user.id);
const comments = await fetchComments(posts[0].id);
2. 并行执行(快)
// ✅ 并行执行(总耗时 ≈ 最慢请求)
const [user, posts, comments] = await Promise.all([
fetchUser(),
fetchPosts(),
fetchComments()
]);
// ✅ 无依赖请求直接触发
const userPromise = fetchUser(); // 立即启动
const postsPromise = fetchPosts(); // 立即启动
const user = await userPromise;
const posts = await postsPromise;
六、高级模式
1. 异步迭代
for await (const chunk of asyncDataStream) {
process(chunk);
}
2. 异步箭头函数
const saveData = async (data) => {
await db.save(data);
return { status: 'success' };
};
3. 立即执行异步函数
(async () => {
const data = await initializeApp();
console.log("应用已初始化:", data);
})();
七、陷阱与解决方案
陷阱 1: await 在循环中的误用
// ❌ 顺序执行(慢)
for (const url of urls) {
const res = await fetch(url); // 依次等待
}
// ✅ 并行执行(快)
const promises = urls.map(url => fetch(url));
const results = await Promise.all(promises);
陷阱 2:忘记 await
async function update() {
// ❌ 忘记 await(不会等待保存)
saveData();
// ✅ 正确
await saveData();
}
陷阱 3:错误处理遗漏
// ❌ 未捕获错误(导致未处理拒绝)
async function dangerous() {
throw new Error("危险操作");
}
dangerous();
// ✅ 安全方案
dangerous().catch(handleError); // 或使用 try/catch
八、最佳实践
-
优先
async/await
+try/catch
:async function main() { try { const data = await criticalOperation(); return transform(data); } catch (error) { recoverFromError(error); return fallbackValue; } }
-
无依赖请求并行化:
async function loadDashboard() { const [user, settings] = await Promise.all([ fetchUser(), fetchSettings() ]); renderUI(user, settings); }
-
避免过度阻塞:
// 允许其他任务执行 await longTask(); setTimeout(() => {}, 0); // 让出线程
-
明确命名异步函数:
// 好 async function fetchUserData() {} // 不好 async function getData() {}
总结对比表
特性 | Promise .then() |
async/await |
---|---|---|
代码风格 | 链式调用 | 同步代码风格 |
可读性 | 嵌套复杂时难读 | 线性结构更清晰 |
错误处理 | .catch() |
try/catch 块 |
调试 | 断点跳转不直观 | 同步式断点调试 |
执行控制 | 自动状态管理 | 手动 await 暂停 |
返回值 | 返回新 Promise | 自动包装为 Promise |
适用场景 | 简单链式调用 | 复杂异步逻辑 |
黄金法则:
- 所有
async
函数都是返回 Promise 的语法糖await
本质是 Promise 的暂停解析器- 使用
try/catch
处理错误,Promise.all
处理并行- 在顶层调用使用
.catch()
防止未处理拒绝
最终建议:在现代 JavaScript 中优先使用 async/await
编写异步代码,兼顾可读性与功能性!
🤔 参考 19
JavaScript 中的 async
和 await
是基于 Promise 的语法糖,用于简化异步操作的处理,使异步代码的书写和阅读更接近同步方式。以下是详细解析:
1. async 函数
- 作用:声明一个异步函数
- 返回值:始终返回一个 Promise 对象
- 若函数返回非 Promise 值,会自动包装为
Promise.resolve(value)
- 若抛出错误,返回
Promise.reject(error)
- 若函数返回非 Promise 值,会自动包装为
async function example() {
return 42; // 等价于 Promise.resolve(42)
}
example().then(console.log); // 输出 42
2. await 表达式
- 作用:暂停异步函数的执行,等待 Promise 的解决
- 只能在
async
函数内部使用 - 行为:
- 若等待的 Promise 成功(fulfilled):返回解决值
- 若 Promise 失败(rejected):抛出拒绝原因(需用 try/catch 捕获)
async function fetchData() {
const response = await fetch('https://api.example.com/data'); // 等待请求完成
const data = await response.json(); // 等待 JSON 解析
return data;
}
3. 错误处理
使用 try/catch
捕获异步错误(替代 Promise 的 .catch()
):
async function loadData() {
try {
const data = await fetch('invalid-url');
} catch (error) {
console.error('请求失败:', error); // 捕获网络错误或拒绝的 Promise
}
}
4. 执行流程详解
console.log('Start');
async function example() {
console.log('Async start');
const result = await new Promise(res => setTimeout(() => res('Done!'), 1000));
console.log(result);
return 'Finished';
}
example().then(console.log);
console.log('End');
/* 输出顺序:
Start
Async start
End
(1秒后)
Done!
Finished
*/
- 同步代码优先执行(输出 Start, Async start, End)
await
暂停函数执行,释放主线程- Promise 完成后恢复函数执行
5. 并行执行优化
多个独立异步操作应并行执行以提高效率:
// 低效 - 顺序执行
async function slow() {
const a = await task1(); // 等待完成
const b = await task2(); // 再开始
}
// 高效 - 并行执行
async function fast() {
const [a, b] = await Promise.all([task1(), task2()]); // 同时启动
}
6. 常见误区
错误:在非 async 函数中使用 await
function fail() {
await promise; // SyntaxError: await is only valid in async functions
}
错误:忘记 await
async function oops() {
const data = fetch('/api'); // 缺少 await! 返回的是 Promise 对象而非数据
console.log(data); // 输出 Promise 实例
}
7. 与传统 Promise 对比
// Promise 链式调用
function oldWay() {
fetch('/api')
.then(response => response.json())
.then(data => console.log(data))
.catch(err => console.error(err));
}
// async/await 方式
async function newWay() {
try {
const response = await fetch('/api');
const data = await response.json();
console.log(data);
} catch (err) {
console.error(err);
}
}
8. 高级用法
立即执行异步函数
(async () => {
const data = await loadResource();
console.log('立即执行', data);
})();
循环中的 await
// 顺序执行异步迭代
async function processArray(array) {
for (const item of array) {
await processItem(item); // 逐个等待完成
}
}
// 并行执行
async function parallelProcess(array) {
await Promise.all(array.map(item => processItem(item)));
}
9. 浏览器与 Node.js 支持
- 现代浏览器(Chrome 55+、Firefox 52+、Safari 10.1+)
- Node.js 7.6+(建议使用 LTS 版本)
总结要点
特性 | 说明 |
---|---|
async 函数 |
总是返回 Promise 对象 |
await |
暂停函数执行,等待 Promise 解决,只能在 async 函数中使用 |
错误处理 | 使用 try/catch 捕获异常 |
执行顺序 | 异步函数不会阻塞主线程,await 会暂停当前函数内后续代码的执行 |
性能优化 | 使用 Promise.all() 并行独立操作 |
核心价值 | 用同步写法处理异步逻辑,显著提升代码可读性和可维护性 |
掌握 async/await
可以显著提升异步代码的可维护性,但在性能关键场景需注意避免不必要的顺序等待。
🤔 参考 20
async/await
是 JavaScript 中处理异步操作的语法糖,基于 Promise 构建,让异步代码的写法更接近同步代码,极大提升了可读性和可维护性。下面详细解析其用法和特性:
一、async:声明异步函数async
关键字用于修饰函数,使其成为异步函数,有以下核心特性:
1. 基本语法
// 函数声明
async function fn() {}
// 函数表达式
const fn = async function() {};
// 箭头函数
const fn = async () => {};
// 对象方法
const obj = {
async method() {}
};
2. 返回值自动包装为 Promise
- 无论
async
函数内部返回什么值,都会被自动包装成一个fulfilled
状态的 Promise。 - 若内部抛出错误,则返回
rejected
状态的 Promise。
async function demo() {
return "成功结果"; // 等价于 return Promise.resolve("成功结果")
}
demo().then(data => console.log(data)); // 输出:成功结果
async function errorDemo() {
throw new Error("出错了"); // 等价于 return Promise.reject(new Error("出错了"))
}
errorDemo().catch(err => console.log(err.message)); // 输出:出错了
二、await:等待 Promise 完成await
关键字只能在 async
函数内部使用,用于"等待"一个 Promise 完成,是 async/await
简化异步代码的核心。
1. 基本语法
async function fn() {
const result = await promiseObj; // 等待 Promise 状态变为 fulfilled
}
2. 工作原理
- 当
await
后面跟一个 Promise 时,会暂停当前async
函数的执行,直到该 Promise 状态变为fulfilled
或rejected
。 - 若 Promise 成功(
fulfilled
),await
会返回 Promise 的结果值。 - 若 Promise 失败(
rejected
),await
会抛出异常,需用try/catch
捕获。
// 模拟一个异步请求
function fetchData() {
return new Promise(resolve => {
setTimeout(() => resolve("异步数据"), 1000);
});
}
async function process() {
console.log("开始");
const data = await fetchData(); // 等待 1 秒,获取结果
console.log("获取到数据:", data); // 输出:获取到数据:异步数据
return data;
}
process();
三、错误处理:try/catchawait
后的 Promise 若变为 rejected
,会抛出异常,必须用 try/catch
捕获,否则会导致整个 async
函数返回的 Promise 变为 rejected
。
function riskyOperation() {
return new Promise((resolve, reject) => {
setTimeout(() => reject(new Error("操作失败")), 1000);
});
}
async function handleRisk() {
try {
const result = await riskyOperation();
console.log("成功:", result); // 不会执行
} catch (error) {
console.log("捕获错误:", error.message); // 输出:捕获错误:操作失败
} finally {
console.log("无论成功失败都会执行"); // 输出:无论成功失败都会执行
}
}
handleRisk();
四、串行与并行:控制异步流程async/await
让异步流程控制更直观,需注意区分串行执行和并行执行。
1. 串行执行(依次执行)
多个 await
依次书写时,会等待前一个完成后再执行下一个,总耗时是各异步操作的总和。
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function serial() {
console.log("开始串行");
await delay(1000); // 等待 1s
await delay(2000); // 再等待 2s(总耗时 ~3s)
console.log("串行结束");
}
serial();
2. 并行执行(同时执行)
若多个异步操作无依赖关系,应同时启动它们再等待所有完成,总耗时是最长的那个操作的时间。
async function parallel() {
console.log("开始并行");
// 同时启动两个异步操作
const promise1 = delay(1000);
const promise2 = delay(2000);
// 等待两者都完成(总耗时 ~2s)
await promise1;
await promise2;
console.log("并行结束");
}
parallel();
3. 批量并行: Promise.all()
处理多个并行操作时,常用 Promise.all()
一次性等待所有结果:
async function batch() {
const promises = [delay(1000), delay(2000), delay(1500)];
const results = await Promise.all(promises); // 等待所有完成(总耗时 ~2s)
console.log("所有操作完成");
}
五、与 Promise.then() 的对比async/await
本质是 Promise 的语法糖,但代码结构更清晰:
场景 | Promise.then() 写法 | async/await 写法 |
---|---|---|
基本流程 | 链式调用 .then() |
同步风格的顺序执行 |
错误处理 | .catch() 链式捕获 |
try/catch 结构化捕获 |
多个依赖操作 | 多层 .then() 嵌套 |
平铺的 await 语句 |
示例对比:
// Promise.then() 写法
fetchUser()
.then(user => fetchPosts(user.id))
.then(posts => fetchComments(posts[0].id))
.then(comments => console.log(comments))
.catch(err => console.log(err));
// async/await 写法
async function getComments() {
try {
const user = await fetchUser();
const posts = await fetchPosts(user.id);
const comments = await fetchComments(posts[0].id);
console.log(comments);
} catch (err) {
console.log(err);
}
}
六、注意事项
-
await
只能在async
函数中使用
若在普通函数中使用await
,会直接报错。 -
async
函数不会阻塞主线程await
只会暂停当前async
函数的执行,但不会阻塞其他代码(如浏览器事件循环)。 -
避免不必要的
await
对已确定的同步值使用await
会多余且降低性能:// 不推荐:对非Promise值使用await const result = await 123; // 推荐:直接使用 const result = 123;
-
处理多个独立异步操作用
Promise.all()
避免用多个await
串行执行无依赖的异步操作(会浪费时间)。
七、总结
async
用于函数变为异步函数,其返回值自动包装为 Promise。await
用于等待 Promise 完成,使异步代码看起来像同步代码。- 用
try/catch
处理await
可能抛出的错误。 - 区分串行和并行执行,优化异步流程效率。
async/await
是目前 JavaScript 异步编程的主流方案,它在 Promise 的基础上提供了更直观、更易维护的语法,尤其成为现代前端框架(如 React、Vue)中处理异步逻辑的首选方式。
JavaScript异步编程: 回调callback , Promise,then,catch,finally , async,await 笔记250810
JavaScript异步,笔记250810
JavaScript的 Promise,then,catch,finally,async,await 笔记250810
JavaScript的 Promise,then 笔记250803
Js的 Promise的 then catch 笔记240222
Promise().then().catch().finally() 笔记250804
Promise的reject处理: then的第二个回调 与 catch回调 笔记250804
JavaScript的 async , await 笔记250808
Promise,then 与 async,await 相互转换 笔记250810
JavaScript的Callback回调函数转Promise().then()和async{await} 笔记250810
更多推荐
所有评论(0)