async-await 是否会阻塞代码的执行
async/await
不会阻塞事件循环或主线程,但会根据上下文对代码执行顺序产生不同影响,具体分为以下两种情况:
一、async 函数外部的代码:不阻塞
async
函数被调用时,会立即返回一个 Promise
对象,不会阻塞外部代码的执行。
示例:
async function fetchData() { /* ... */ }
fetchData(); // 立即返回 Promise,不会阻塞后续代码
console.log("外部代码继续执行"); // 会立即执行
主线程/UI 渲染:async
函数的调用不会阻塞主线程或界面渲染,事件循环仍可处理其他任务。
二、async 函数内部的代码:await 会暂停后续代码的执行
在 async
函数内部,遇到 await
时,当前函数的后续代码会暂停执行,直到等待的 Promise
状态变为 resolved
或 rejected
。
示例:
async function example() {
const result = await fetchData(); // 暂停后续代码,等待 fetchData 完成
console.log("此处代码需等待 await 完成"); // 在 await 后执行
}
阻塞范围仅限于当前函数:暂停仅影响当前 async
函数的内部逻辑,不会阻塞其他外部代码或事件循环。
示例:
async function task1() { await delay(1000); }
async function task2() { /* ... */ }
task1(); // 内部暂停,但 task2() 仍可并行执行
task2();
三、潜在误解与注意事项
- 长时间异步操作:若
async
函数中某个await
的异步操作耗时过长(如网络请求),虽然不会阻塞主线程,但会导致当前函数的后续逻辑延迟执行,可能影响用户体验。 - 同步代码混合时:若
async
函数中存在同步代码(如循环或复杂计算),这些代码仍会阻塞当前函数内的后续逻辑(但不会阻塞主线程)。
四、总结
async-await
在 JavaScript
中用于简化异步操作的处理,但它本身并不会阻塞代码执行,它允许以一种看似同步的方式编写异步代码,而实际上只是在特定函数的上下文中暂停执行,不会阻塞整个程序的运行。
async function asyncFunction() {
console.log('Async function starts');
await new Promise(resolve => setTimeout(resolve, 2000));
console.log('Async function ends after waiting');
}
console.log('Script starts');
asyncFunction();
console.log('Script continues after calling asyncFunction');
对应输出
Script starts
Async function starts
Script continues after calling asyncFunction
(等待2秒)
Async function ends after waiting
上述代码在执行asyncFunction
后,输出Asyncfunction starts
,但遇到第 3行的 await
语句后,立即“脱离”函数逻辑,并执行第9行代码,输出Script continues after calling asyncFunction
,再往后,等待 await
后面的 promise
执行完毕后,再输出第4行内容。
因此,async-await
并不阻塞代码整体流程,而是借助JS 的事件循环机制(微任务),脱离当前函数,交出 cpu
控制权,执行函数后面的逻辑。