Async/await是阻塞的吗?为何其运行结果与Promise写法存在差异?
Async/await非阻塞特性的常见误解解答
首先要明确async/await的「非阻塞」定义:它只会暂停当前async函数内部await语句之后的代码执行,不会阻塞整个JavaScript主线程的其他同步任务、事件回调执行,这才是非阻塞的核心含义,不是指不阻塞当前async函数内部的后续逻辑。
两种写法的执行流程差异
1. async/await写法执行顺序
function resolveAfter2Seconds() { return new Promise(resolve => { setTimeout(() => { resolve('resolved'); }, 2000); }); } async function asyncCall() { console.log('calling'); // 遇到await关键字 const result = await resolveAfter2Seconds(); console.log(result); console.log('calling end'); } asyncCall();
执行流程:
- 调用
asyncCall(),首先同步执行console.log('calling'),输出calling - 执行
resolveAfter2Seconds(),返回Pending状态的Promise,同时2秒延时的setTimeout进入宏任务队列等待执行 - 触发await规则:暂停当前async函数后续所有代码的执行,立刻让出主线程(这就是非阻塞的体现,如果此时全局有其他同步代码会直接执行,不会等待2秒)
- 2秒后Promise状态变为resolved,恢复执行async函数中await后的代码:先输出
resolved,再输出calling end
2. Promise链式写法执行顺序
async function asyncCall() { console.log('calling'); // 无await,直接执行Promise链式调用 resolveAfter2Seconds().then(result=>{ console.log(result); }); console.log('calling end'); }
执行流程:
- 调用
asyncCall(),同步执行console.log('calling'),输出calling - 执行
resolveAfter2Seconds().then(...),同样返回Pending状态的Promise,setTimeout进入宏任务队列 - 没有await关键字,不会暂停当前async函数的执行,直接执行后续代码
console.log('calling end'),输出calling end - 2秒后Promise状态变为resolved,执行then的回调函数,输出
resolved
非阻塞特性的验证
你可以在asyncCall()调用后加一行全局同步代码测试:
asyncCall(); console.log('全局同步代码执行');
不管用await写法还是Promise链式写法,全局同步代码执行都会在calling之后立刻输出,不会等待2秒,这就是async/await非阻塞的直观体现。
内容的提问来源于stack exchange,提问作者Taimoor Hussain Musa
相关产品推荐
相关产品推荐

