HTML本身无async函数,async/await是JavaScript特性;需在type="module"脚本或async函数内使用,并始终检查res.ok和用try/catch处理错误。

HTML 本身没有 async 函数——这是个常见误解。async/await 是 JavaScript 的语法特性,和 HTML 无关;你不能在 HTML 标签属性或纯 HTML 文档里写 async 函数或用 await。真正能用 async/await 简化 fetch 请求的,是嵌入在 HTML 中的 <script>(尤其是模块脚本),或外部 JS 文件。
为什么直接在 script 标签里写 async/await 会报错?
常见错误现象:Uncaught SyntaxError: await is only valid in async function 或 Uncaught SyntaxError: Unexpected identifier,尤其出现在顶层(top-level)await 时。
- 浏览器默认的
<script>是非模块环境,不支持顶层await - 即使加了
async属性(如<script async>),那只是控制脚本加载时机,跟async函数无关 - 想用
await,必须包裹在async函数内,或启用 ES 模块(type="module")
如何在 HTML 页面中正确使用 async/await 调用 fetch?
最稳妥、兼容性好(Chrome 63+/Firefox 57+)的方式:用 type="module" 启用顶层 await,并配合 fetch。
- HTML 中这样引入脚本:
<script type="module" src="app.js"></script>(或内联<script type="module">...</script>) - 模块环境下允许顶层
await,所以你可以直接写:const res = await fetch('/api/data');<br>const data = await res.json(); - 如果不用模块,就老老实实包一层函数:
async function loadData() {<br> const res = await fetch('/api/data');<br> return res.json();<br>}<br>loadData().then(console.log);
fetch + async/await 容易踩的坑
fetch 不会在 HTTP 状态码异常(如 404、500)时自动 reject,这和很多人直觉相反。
-
await fetch('/404')不会抛错,res.ok才是判断请求成功的依据 - 漏判
res.ok导致后续res.json()解析空响应体而报Unexpected end of JSON input - 网络失败(如断网)才会触发 reject,所以仍需
try/catch捕获底层错误 - 示例修正写法:
try {<br> const res = await fetch('/api/user');<br> if (!res.ok) throw new Error(`HTTP ${res.status}`);<br> const user = await res.json();<br> console.log(user);<br>} catch (err) {<br> console.error('Fetch failed:', err);<br>}
真正要小心的不是语法怎么写,而是误以为 async/await 能自动处理 HTTP 语义错误——它只消除了回调嵌套,没改变 fetch 的设计契约。每次 await fetch() 后,res.ok 和 try/catch 仍是必选项。



















