异步 Promise 与 async/await
回调、fetch、对接本站 API。
异步 Promise 与 async/await
这一课你将能做到
- 解释为什么网络请求不能「写在下一行就当成已经有结果」
- 用
async/await+try/catch写一次取数流程 - 给界面加上「加载中 / 成功 / 失败」三种状态中的至少两种
为什么要学
fetch 去服务器拿数据需要时间。
若 JS 死等,页面就卡死——所以用异步:先继续干别的,结果以后再处理。
人话:你点了外卖(发起请求),先干别的事;外卖到了(Promise 完成)再吃饭(更新页面)。
本站前端调后端 API、任何真实产品拉列表,都建立在异步之上。
先建立图像
Promise(承诺)三种状态:
pending 进行中
fulfilled 成功,得到值
rejected 失败,得到错误
async 函数里:
await 某个 Promise → 等到结束再往下走
(看起来像同步,仍不卡死浏览器主线程)
点击「加载」
→ 显示「加载中」
→ await fetch(...)
→ 成功:显示数据 / 失败:显示错误
跟着做
步骤 1:认识延迟与 await
function wait(ms) {
// 返回一个「ms 毫秒后完成」的 Promise
return new Promise(function (resolve) {
setTimeout(resolve, ms);
});
}
async function demo() {
console.log("开始");
await wait(500);
console.log("0.5 秒后");
}
demo();
console.log("demo() 已调用,但这行可能先打印");
你应看到:demo() 已调用… 往往出现在「0.5 秒后」之前——说明异步不会堵住后面的同步代码。
步骤 2:忘记 await 会怎样(常见 bug)
async function f() {
const p = wait(100); // 没 await
console.log(p); // Promise 对象,不是「结束之后的值」
const done = await wait(100);
console.log("await 之后:", done); // undefined(因 resolve 没传值)
}
f();
新手最常见问题:把 Promise 当成最终数据。看见 Promise { <pending> } 就要怀疑漏了 await。
步骤 3:假接口 + 界面三种状态
下面用公开测试接口;若网络不通可改成 await wait(500) 自己返回假数据。
保存为 js-async.html:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>异步</title>
</head>
<body>
<button type="button" id="load">加载探测文本</button>
<p id="out">尚未加载</p>
<script>
const out = document.getElementById("out");
function wait(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
async function loadPoem() {
out.textContent = "加载中…";
try {
const res = await fetch("https://www.cloudflare.com/cdn-cgi/trace");
if (!res.ok) throw new Error("HTTP " + res.status);
const text = await res.text();
out.textContent = text.slice(0, 120) + "…";
} catch (err) {
out.textContent = "失败:" + err.message;
console.error(err);
}
}
document.getElementById("load").addEventListener("click", function () {
loadPoem();
});
// 离线演练:把 loadPoem 换成下面这段即可
async function loadFake() {
out.textContent = "加载中…";
try {
await wait(500);
out.textContent = "假数据:加载成功";
} catch (err) {
out.textContent = "失败:" + err.message;
}
}
</script>
</body>
</html>