async函数本质是Promise的语法糖,返回Promise对象;await仅在async函数内有效,暂停当前函数但不阻塞主线程;多请求需用Promise.all并发;错误必须用try/catch显式处理。

async 函数本质是语法糖,不是新机制
它只是 Promise 的封装层,底层仍依赖 Promise 状态流转。声明一个 async 函数,等价于返回一个自动 resolve 的 Promise:
async function foo() {
return 'done';
}
// 等价于
function foo() {
return Promise.resolve('done');
}
这意味着:即使函数体里没写 await,调用它仍会返回 Promise;你不能直接拿到返回值,必须用 .then() 或外层再套 await。
常见误操作:const res = foo() 拿到的是 Promise 对象,不是字符串 'done' —— 这是初学者最常卡住的地方。
await 只能在 async 函数内部使用
await 不是全局关键字,它依赖 async 函数提供的执行上下文。在普通函数、事件回调、setTimeout 回调里直接写 await 会报错:SyntaxError: await is only valid in async functions。
立即学习“Java免费学习笔记(深入)”;
- ✅ 正确:在
async函数中await fetch('/api') - ❌ 错误:在
document.addEventListener('click', () => { await getData(); })中直接await - ✅ 替代方案:把事件回调本身声明为
async,或改用.then()
注意:箭头函数也能 async,但必须显式标注:const handler = async () => { await apiCall(); }。
await 会暂停当前 async 函数,但不阻塞主线程
这是关键理解点。await 暂停的是当前 async 函数的执行流(类似“让出控制权”),JS 引擎会继续处理其他任务(如渲染、其他事件),等 Promise settle 后再恢复该函数。
所以以下代码不会卡死页面:
async function loadAndRender() {
const data = await fetch('/data').then(r => r.json());
document.body.innerHTML = JSON.stringify(data);
}
但要注意顺序陷阱:
- 多个
await是串行的:后一个要等前一个完成才开始 - 想并发执行?得用
Promise.all([p1, p2])包裹,再await它 -
await Promise.all([fetch('/a'), fetch('/b')])比两个单独await快得多
错误处理必须显式做,try/catch 不是可选的
await 遇到 rejected 的 Promise 会直接抛出异常,不加 try/catch 就会变成未捕获异常(unhandled rejection),可能触发 unhandledrejection 事件甚至崩溃。
不要这样写:
async function bad() {
const res = await fetch('/fail'); // 404 时这里就 throw
return res.json();
}
应该:
async function good() {
try {
const res = await fetch('/fail');
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return await res.json();
} catch (err) {
console.error('API failed:', err);
return null;
}
}
容易被忽略的一点:被 catch 捕获的错误,**不是原始 Promise reject 的值本身**,而是它包装后的 Error 实例(尤其在 fetch 场景下,需手动检查 res.ok)。










