await 等待的是表达式被自动转换后的 promise 值:若为 promise 则直接等待,若为普通值则等效 promise.resolve(),若为 thenable 则尝试兼容处理;非 promise 值瞬间完成,promise.reject 或同步抛错均触发 catch,且 await 仅解包最外层 promise。

await 等待的不是“异步操作本身”,而是它返回的值——这个值会被自动转换为 Promise,再进入等待流程。理解这个转换过程,是避免隐式错误和写出健壮 async 函数的关键。
await 实际等待的是 Promise
await 后面可以写任意表达式,但 JavaScript 会立即把它“包装”成 Promise:
- 如果表达式本身是 Promise(比如 fetch()、new Promise(...)),await 就直接等待它 resolve 或 reject;
- 如果是普通值(如字符串、数字、对象、undefined),JavaScript 会等效调用 Promise.resolve(value),生成一个已 fulfilled 的 Promise,然后立刻 resolve 返回该值;
- 如果是 thenable 对象(即有 .then 方法的对象),await 会尝试以 Promise 兼容方式处理它,但行为可能不完全等同于原生 Promise,需谨慎使用。
非 Promise 值不会真正“异步等待”
写 await 42 或 await {a: 1} 看似奇怪,但语法合法——它们不会卡住执行,而是瞬间完成:
- await 42 等价于 await Promise.resolve(42),结果就是 42;
- await null 返回 null;
- 这种写法虽无错,但失去异步意义,容易误导后续维护者,建议仅用于占位或调试场景。
Promise.reject 和 throw 都会中断流程
await 不区分“主动 reject”和“同步抛错”,只要 Promise 被拒绝或表达式抛出异常,都会跳出当前 await 行,跳转到最近的 catch 块:
- await Promise.reject('fail') → 触发 catch;
- await someFunctionThatThrows() → 即使函数没返回 Promise,也会被包装并立即 reject;
- 这意味着:不要依赖“await 后是否真有异步”来判断错误路径,统一用 try/catch 捕获。
await 处理链式 Promise 时只等一层
await 总是对最外层 Promise 进行解包,不会递归展开嵌套 Promise:
- await Promise.resolve(Promise.resolve(123)) → 结果是 123(自动扁平化);
- await (async () => Promise.resolve(456))() → 也得到 456;
- 这是 Promise.resolve 的规范行为,不是 await 特有逻辑,但它让多层异步嵌套在语义上更“透明”。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











