Promise
杯子是一个段落,#cup。一开始是 blank,脚本在要茶之前先写成 waiting。
pour 不返回那杯茶。它返回一个 Promise。你用 then 请这个 Promise 稍后把茶写上。pour 下面那一行仍是 waiting。这一行是 waiting / lida tea。
不是刚才端上来的那杯
上一页把 done 交给 serve。serve 在返回之前就调用了函数,所以下面的记录已经是 lida tea / poured。那里没有人在等。
这里交给 then 的函数不在下一行运行。pour 先返回。茶要等这段脚本结束才出现。
三种状态
Promise 在决定之前是 pending。resolve 用一个值完成它。reject 用一个原因拒绝它。then 只在完成时运行。catch 只在拒绝时运行。这一页没有计时器。执行器立刻调用 resolve 或 reject,处理函数仍然要等到脚本结束。
📊 三种状态
| 状态 | 你看到什么 | 容易搞混 |
|---|---|---|
| pending | 杯子仍写着 waiting | 茶已经在杯子上 |
| fulfilled | then 收到 lida tea | catch 也会跑 |
| rejected | catch 收到 no leaves | then 收到茶 |
执行器是现在,处理函数不是
交给 new Promise 的函数立刻运行。所以 resolve("lida tea") 可能发生在 pour 返回之前。交给 then 的函数不同。它排队。pour(...) 后面那一行运行时,杯子仍写着 waiting。
下一行还在等
pour("lida") 把一个 Promise 放进 order。杯子已经是 waiting。记录是这个词,不是茶。
function pour(order) {
return new Promise(function (resolve, reject) {
if (order === "") {
reject("no leaves");
return;
}
resolve(order + " tea");
});
}
let cup = document.getElementById("cup");
cup.textContent = "waiting";
let order = pour("lida");
console.log(cup.textContent);
记录是 waiting。order 是 Promise。它不是文本 lida tea。
then 收到茶
用一个函数调用 then。这个函数拿到传给 resolve 的值。它写下茶并记录。这个记录不是下一行的记录。是 then 里面的记录。
function pour(order) {
return new Promise(function (resolve, reject) {
if (order === "") {
reject("no leaves");
return;
}
resolve(order + " tea");
});
}
let cup = document.getElementById("cup");
pour("lida").then(function (drink) {
cup.textContent = drink;
console.log(cup.textContent);
});
记录是 lida tea。空文本到不了这个处理函数。
没有茶叶
pour("") 调用 reject("no leaves") 然后返回。catch 拿到这个原因。then 不运行。
function pour(order) {
return new Promise(function (resolve, reject) {
if (order === "") {
reject("no leaves");
return;
}
resolve(order + " tea");
});
}
pour("").catch(function (reason) {
console.log(reason);
});
记录是 no leaves。
Promise 不是那杯茶
order.then 是一个函数。由此知道 order 是 Promise,不是你要的文本。把 Promise 和 "lida tea" 比较会是错的,这段只打印 then 的类型。
function pour(order) {
return new Promise(function (resolve, reject) {
if (order === "") {
reject("no leaves");
return;
}
resolve(order + " tea");
});
}
let order = pour("lida");
console.log(typeof order.then);
记录是 function。
杯子下面那一行
脚本把杯子设成 waiting,并立刻推入这个词。then 推入 lida tea,再把两个词接起来。拼接在 then 里面,所以在脚本之后,不在下一行。
<!DOCTYPE html>
<html>
<head>
<title>promised-cup — page</title>
</head>
<body>
<p id="cup">blank</p>
<p id="line">…</p>
<script>
function pour(order) {
return new Promise(function (resolve, reject) {
if (order === "") {
reject("no leaves");
return;
}
resolve(order + " tea");
});
}
let cup = document.getElementById("cup");
let seen = [];
cup.textContent = "waiting";
seen.push(cup.textContent);
pour("lida").then(function (drink) {
seen.push(drink);
cup.textContent = drink;
document.getElementById("line").textContent = seen.join(" / ");
});
</script>
</body>
</html>
这一行是 waiting / lida tea。waiting 是立刻的。lida tea 在 then 里到来。blank 这个词没了。lida tea / poured 是上一页。
在柜台
- 把杯子设成 waiting,调用
pour("lida"),并立刻记录杯子。记录是 waiting。 - 在
then里把茶写到杯子上。那个记录是 lida tea。 - 调用
pour(""),用catch接住原因。记录是 no leaves。 - 读取
typeof order.then。记录是 function。 - 读页面这一行:waiting / lida tea。
柜台容易错的地方
在 then 运行之前,杯子写的是 waiting。它不写 poured。
- 以为
pour下面的记录是 lida tea - 把返回值当成茶的文本
- 空订单用
then,漏掉 no leaves - 给 lida 用
catch,却等着 no leaves - 把这一行读成 lida tea / poured
记住这些
pour返回 Promise,不返回文本 lida tea- 下一行仍记录 waiting
then在这段脚本之后收到 lida tea- 空订单以 no leaves 被拒绝,
catch记录它 - 页面这一行是 waiting / lida tea
🧠 测试您的知识
测试您的知识
通过这个互动测验挑战自己,看看你对这个主题的理解程度如何
📝 说明
- 仔细阅读每个问题
- 为每个问题选择最佳答案
- 您可以随时重新参加测验
- 您的进度将显示在顶部