正在加载...

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。记录是这个词,不是茶。

杯子还在等

javascript
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 里面的记录。

then 写下茶

javascript
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 不运行。

接住空订单

javascript
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 的类型。

then 是函数

javascript
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 里面,所以在脚本之后,不在下一行。

页面演示 — 答应的杯子

html
<!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 是上一页。

在柜台

  1. 把杯子设成 waiting,调用 pour("lida"),并立刻记录杯子。记录是 waiting。
  2. 在 then 里把茶写到杯子上。那个记录是 lida tea。
  3. 调用 pour(""),用 catch 接住原因。记录是 no leaves。
  4. 读取 typeof order.then。记录是 function。
  5. 读页面这一行: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

🧠 测试您的知识

准备开始

测试您的知识

通过这个互动测验挑战自己,看看你对这个主题的理解程度如何

❓
5
问题
🎯
70%
及格要求
♾️
∞
时间
🔄
∞
尝试次数

📝 说明

  • 仔细阅读每个问题
  • 为每个问题选择最佳答案
  • 您可以随时重新参加测验
  • 您的进度将显示在顶部