commit 50392947b6838829432e25f898d3e389d2eb8a2b
Author: YuanJin <277739025@qq.com>
Date: Mon Nov 1 11:35:48 2021 +0800
init
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ffcf992
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+*.dio
\ No newline at end of file
diff --git a/01. Promise基础/1.js b/01. Promise基础/1.js
new file mode 100644
index 0000000..bf9272c
--- /dev/null
+++ b/01. Promise基础/1.js
@@ -0,0 +1,69 @@
+// 向某位女生发送一则表白短信
+// name: 女神的姓名
+// onFulffiled: 成功后的回调
+// onRejected: 失败后的回调
+function sendMessage(name, onFulffiled, onRejected) {
+ // 模拟 发送表白短信
+ console.log(
+ `邓哥 -> ${name}:最近有谣言说我喜欢你,我要澄清一下,那不是谣言😘`
+ );
+ console.log(`等待${name}回复......`);
+ // 模拟 女神回复需要一段时间
+ setTimeout(() => {
+ // 模拟 有10%的几率成功
+ if (Math.random() <= 0.1) {
+ // 成功,调用 onFuffiled,并传递女神的回复
+ onFulffiled(`${name} -> 邓哥:我是九,你是三,除了你还是你😘`);
+ } else {
+ // 失败,调用 onRejected,并传递女神的回复
+ onRejected(`${name} -> 邓哥:你是个好人😜`);
+ }
+ }, 1000);
+}
+
+// 首先向 李建国 发送消息
+sendMessage(
+ '李建国',
+ (reply) => {
+ // 如果成功了,输出回复的消息后,结束
+ console.log(reply);
+ },
+ (reply) => {
+ // 如果失败了,输出回复的消息后,向 王富贵 发送消息
+ console.log(reply);
+ sendMessage(
+ '王富贵',
+ (reply) => {
+ // 如果成功了,输出回复的消息后,结束
+ console.log(reply);
+ },
+ (reply) => {
+ // 如果失败了,输出回复的消息后,向 周聚财 发送消息
+ console.log(reply);
+ sendMessage(
+ '周聚财',
+ (reply) => {
+ // 如果成功了,输出回复的消息后,结束
+ console.log(reply);
+ },
+ (reply) => {
+ // 如果失败了,输出回复的消息后,向 刘人勇 发送消息
+ console.log(reply);
+ sendMessage(
+ '刘人勇',
+ (reply) => {
+ // 如果成功了,输出回复的消息后,结束
+ console.log(reply);
+ },
+ (reply) => {
+ // 如果失败了,就彻底没戏了
+ console.log(reply);
+ console.log('邓哥命犯天煞孤星,注定孤独终老!!');
+ }
+ );
+ }
+ );
+ }
+ );
+ }
+);
diff --git a/01. Promise基础/2.js b/01. Promise基础/2.js
new file mode 100644
index 0000000..9234c97
--- /dev/null
+++ b/01. Promise基础/2.js
@@ -0,0 +1,23 @@
+const pro = new Promise((resolve, reject) => {
+ console.log('开始百米短跑');
+ const duration = Math.floor(Math.random() * 5000);
+
+ setTimeout(() => {
+ if (Math.random() < 0.5) {
+ // 成功
+ resolve(duration); // 将任务从挂起->完成
+ } else {
+ // 失败,脚扭伤了
+ reject('脚扭伤了!');
+ }
+ }, duration);
+});
+
+pro.then(
+ (data) => {
+ console.log('on yeah! 我跑了', data, '秒');
+ },
+ (reason) => {
+ console.log('不好意思,', reason);
+ }
+);
diff --git a/01. Promise基础/3.js b/01. Promise基础/3.js
new file mode 100644
index 0000000..4345d8c
--- /dev/null
+++ b/01. Promise基础/3.js
@@ -0,0 +1,33 @@
+// 向某位女生发送一则表白短信
+// name: 女神的姓名
+// onFulffiled: 成功后的回调
+// onRejected: 失败后的回调
+function sendMessage(name) {
+ return new Promise((resolve, reject) => {
+ // 模拟 发送表白短信
+ console.log(
+ `邓哥 -> ${name}:最近有谣言说我喜欢你,我要澄清一下,那不是谣言😘`
+ );
+ console.log(`等待${name}回复......`);
+ // 模拟 女神回复需要一段时间
+ setTimeout(() => {
+ // 模拟 有10%的几率成功
+ if (Math.random() <= 0.1) {
+ // 成功,调用 onFuffiled,并传递女神的回复
+ resolve(`${name} -> 邓哥:我是九,你是三,除了你还是你😘`);
+ } else {
+ // 失败,调用 onRejected,并传递女神的回复
+ reject(`${name} -> 邓哥:你是个好人😜`);
+ }
+ }, 1000);
+ });
+}
+
+sendMessage('李建刚').then(
+ (reply) => {
+ console.log('成功!', reply);
+ },
+ (reply) => {
+ console.log('失败!', reply);
+ }
+);
diff --git a/01. Promise基础/笔记.md b/01. Promise基础/笔记.md
new file mode 100644
index 0000000..1bede83
--- /dev/null
+++ b/01. Promise基础/笔记.md
@@ -0,0 +1,206 @@
+> 本节课的任务:
+>
+> 1. 理解Promise A+规范的基本概念
+> 2. 学会创建Promise
+> 3. 学会针对Promise进行后续处理
+
+# 邓哥的烦恼
+
+邓哥心中有很多女神,他今天下定决心,要向这些女神表白,他认为,只要女神够多,根据概率学原理,总有一个会接收他
+
+稳妥起见,邓哥决定使用**串行**的方式进行表白:先给第1位女神发送短信,然后等待女神的回应,如果成功了,就结束,如果失败了,则再给第2位女神发送短信,依次类推
+
+
+
+邓哥的女神一共有4位,名字分别是:李建国、王富贵、周聚财、刘人勇
+
+发短信是一个重复性的劳动,邓哥是个程序员,因此决定用函数封装这个动作
+
+```js
+// 向某位女生发送一则表白短信
+// name: 女神的姓名
+// onFulffiled: 成功后的回调
+// onRejected: 失败后的回调
+function sendMessage(name, onFulffiled, onRejected) {
+ // 模拟 发送表白短信
+ console.log(
+ `邓哥 -> ${name}:最近有谣言说我喜欢你,我要澄清一下,那不是谣言😘`
+ );
+ console.log(`等待${name}回复......`);
+ // 模拟 女神回复需要一段时间
+ setTimeout(() => {
+ // 模拟 有10%的几率成功
+ if (Math.random() <= 0.1) {
+ // 成功,调用 onFuffiled,并传递女神的回复
+ onFulffiled(`${name} -> 邓哥:我是九,你是三,除了你还是你😘`);
+ } else {
+ // 失败,调用 onRejected,并传递女神的回复
+ onRejected(`${name} -> 邓哥:你是个好人😜`);
+ }
+ }, 1000);
+}
+```
+
+有了这个函数后,邓哥于是开始编写程序发送短信了
+
+```js
+// 首先向 李建国 发送消息
+sendMessage(
+ '李建国',
+ (reply) => {
+ // 如果成功了,输出回复的消息后,结束
+ console.log(reply);
+ },
+ (reply) => {
+ // 如果失败了,输出回复的消息后,向 王富贵 发送消息
+ console.log(reply);
+ sendMessage(
+ '王富贵',
+ (reply) => {
+ // 如果成功了,输出回复的消息后,结束
+ console.log(reply);
+ },
+ (reply) => {
+ // 如果失败了,输出回复的消息后,向 周聚财 发送消息
+ console.log(reply);
+ sendMessage(
+ '周聚财',
+ (reply) => {
+ // 如果成功了,输出回复的消息后,结束
+ console.log(reply);
+ },
+ (reply) => {
+ // 如果失败了,输出回复的消息后,向 刘人勇 发送消息
+ console.log(reply);
+ sendMessage(
+ '刘人勇',
+ (reply) => {
+ // 如果成功了,输出回复的消息后,结束
+ console.log(reply);
+ },
+ (reply) => {
+ // 如果失败了,就彻底没戏了
+ console.log(reply);
+ console.log('邓哥命犯天煞孤星,注定孤独终老!!');
+ }
+ );
+ }
+ );
+ }
+ );
+ }
+);
+```
+
+该程序完成后,邓哥内心是崩溃的
+
+这一层一层的回调嵌套,形成了传说中的「**回调地狱 callback hell**」
+
+邓哥是个完美主义者,怎么能忍受这样的代码呢?
+
+要解决这样的问题,需要Promise出马
+
+# Promise规范
+
+Promise是一套专门处理异步场景的规范,它能有效的避免回调地狱的产生,使异步代码更加清晰、简洁、统一
+
+这套规范最早诞生于前端社区,规范名称为[Promise A+](https://promisesaplus.com/)
+
+该规范出现后,立即得到了很多开发者的响应
+
+Promise A+ 规定:
+
+1. 所有的异步场景,都可以看作是一个异步任务,每个异步任务,在JS中应该表现为一个**对象**,该对象称之为**Promise对象**,也叫做任务对象
+
+
+
+2. 每个任务对象,都应该有两个阶段、三个状态
+
+
+
+ 根据常理,它们之间存在以下逻辑:
+
+ - 任务总是从未决阶段变到已决阶段,无法逆行
+ - 任务总是从挂起状态变到完成或失败状态,无法逆行
+ - 时间不能倒流,历史不可改写,任务一旦完成或失败,状态就固定下来,永远无法改变
+
+3. `挂起->完成`,称之为`resolve`;`挂起->失败`称之为`reject`。任务完成时,可能有一个相关数据;任务失败时,可能有一个失败原因。
+
+ 
+
+4. 可以针对任务进行后续处理,针对完成状态的后续处理称之为onFulfilled,针对失败的后续处理称之为onRejected
+
+ 
+
+# Promise API
+
+ES6提供了一套API,实现了Promise A+规范
+
+基本使用如下:
+
+```js
+// 创建一个任务对象,该任务立即进入 pending 状态
+const pro = new Promise((resolve, reject) => {
+ // 任务的具体执行流程,该函数会立即被执行
+ // 调用 resolve(data),可将任务变为 fulfilled 状态, data 为需要传递的相关数据
+ // 调用 reject(reason),可将任务变为 rejected 状态,reason 为需要传递的失败原因
+});
+
+pro.then(
+ (data) => {
+ // onFulfilled 函数,当任务完成后,会自动运行该函数,data为任务完成的相关数据
+ },
+ (reason) => {
+ // onRejected 函数,当任务失败后,会自动运行该函数,reason为任务失败的相关原因
+ }
+);
+```
+
+# 邓哥的解决方案
+
+学习了ES6的Promise后,邓哥决定对`sendMessage`函数进行改造,改造结果如下:
+
+```js
+// 向某位女生发送一则表白短信
+// name: 女神的姓名
+// 该函数返回一个任务对象
+function sendMessage(name) {
+ return new Promise((resolve, reject) => {
+ // 模拟 发送表白短信
+ console.log(
+ `邓哥 -> ${name}:最近有谣言说我喜欢你,我要澄清一下,那不是谣言😘`
+ );
+ console.log(`等待${name}回复......`);
+ // 模拟 女神回复需要一段时间
+ setTimeout(() => {
+ // 模拟 有10%的几率成功
+ if (Math.random() <= 0.1) {
+ // 成功,调用 resolve,并传递女神的回复
+ resolve(`${name} -> 邓哥:我是九,你是三,除了你还是你😘`);
+ } else {
+ // 失败,调用 reject,并传递女神的回复
+ reject(`${name} -> 邓哥:你是个好人😜`);
+ }
+ }, 1000);
+ });
+}
+```
+
+之后,就可以使用该函数来发送消息了
+
+```js
+sendMessage('李建国').then(
+ (reply) => {
+ // 女神答应了,输出女神的回复
+ console.log(reply);
+ },
+ (reason) => {
+ // 女神拒绝了,输出女神的回复
+ console.log(reason);
+ }
+);
+```
+
+> 至此,回调地狱的问题仍然没能解决
+>
+> 要解决回调地狱,还需要进一步学习Promise的知识
\ No newline at end of file
diff --git a/01. Promise基础/练习题/p1.js b/01. Promise基础/练习题/p1.js
new file mode 100644
index 0000000..729673d
--- /dev/null
+++ b/01. Promise基础/练习题/p1.js
@@ -0,0 +1,12 @@
+//1. 完成下面的函数
+
+/**
+ * 延迟一段指定的时间
+ * @param {Number} duration 等待的时间
+ * @returns {Promise} 返回一个任务,该任务在指定的时间后完成
+ */
+function delay(duration) {}
+
+// 2. 按照要求,调用delay函数,完成程序
+
+// 利用delay函数,等待1秒钟,输出:finish
diff --git a/01. Promise基础/练习题/p2.html b/01. Promise基础/练习题/p2.html
new file mode 100644
index 0000000..743c413
--- /dev/null
+++ b/01. Promise基础/练习题/p2.html
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+ Document
+
+
+
+
+
+
+
diff --git a/01. Promise基础/练习题/p3.html b/01. Promise基础/练习题/p3.html
new file mode 100644
index 0000000..884419f
--- /dev/null
+++ b/01. Promise基础/练习题/p3.html
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+ Document
+
+
+
+
+
+
+
diff --git a/01. Promise基础/练习题/p4.js b/01. Promise基础/练习题/p4.js
new file mode 100644
index 0000000..caf5cdf
--- /dev/null
+++ b/01. Promise基础/练习题/p4.js
@@ -0,0 +1,16 @@
+// 下面的任务最终状态是什么,相关的数据或失败原因是什么,最终输出什么
+
+new Promise((resolve, reject) => {
+ console.log('任务开始');
+ resolve(1);
+ reject(2);
+ resolve(3);
+ console.log('任务结束');
+});
+
+new Promise((resolve, reject) => {
+ console.log('任务开始');
+ resolve(1);
+ resolve(2);
+ console.log('任务结束');
+});
diff --git a/01. Promise基础/练习题参考答案/p1.js b/01. Promise基础/练习题参考答案/p1.js
new file mode 100644
index 0000000..76401fd
--- /dev/null
+++ b/01. Promise基础/练习题参考答案/p1.js
@@ -0,0 +1,21 @@
+//1. 完成下面的函数
+
+/**
+ * 延迟一段指定的时间
+ * @param {Number} duration 等待的时间
+ * @returns {Promise} 返回一个任务,该任务在指定的时间后完成
+ */
+function delay(duration) {
+ return new Promise((resolve) => {
+ setTimeout(() => {
+ resolve();
+ }, duration);
+ });
+}
+
+// 2. 按照要求,调用delay函数,完成程序
+
+// 利用delay函数,等待1秒钟,输出:finish
+delay(1000).then(() => {
+ console.log('finish');
+});
diff --git a/01. Promise基础/练习题参考答案/p2.html b/01. Promise基础/练习题参考答案/p2.html
new file mode 100644
index 0000000..36ade7e
--- /dev/null
+++ b/01. Promise基础/练习题参考答案/p2.html
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+ Document
+
+
+
+
+
+
+
diff --git a/01. Promise基础/练习题参考答案/p3.html b/01. Promise基础/练习题参考答案/p3.html
new file mode 100644
index 0000000..dc520ca
--- /dev/null
+++ b/01. Promise基础/练习题参考答案/p3.html
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+ Document
+
+
+
+
+
+
+
diff --git a/01. Promise基础/练习题参考答案/p4.js b/01. Promise基础/练习题参考答案/p4.js
new file mode 100644
index 0000000..413ef23
--- /dev/null
+++ b/01. Promise基础/练习题参考答案/p4.js
@@ -0,0 +1,18 @@
+// 下面的任务最终状态是什么,相关的数据或失败原因是什么,最终输出什么
+
+const pro1 = new Promise((resolve, reject) => {
+ console.log('任务开始');
+ resolve(1);
+ reject(2); // 无效
+ resolve(3); // 无效
+ console.log('任务结束');
+});
+
+console.log(pro1);
+
+// new Promise((resolve, reject) => {
+// console.log('任务开始');
+// resolve(1);
+// resolve(2); // 无效
+// console.log('任务结束');
+// });
diff --git a/02. Promise的链式调用/1.js b/02. Promise的链式调用/1.js
new file mode 100644
index 0000000..4a425a5
--- /dev/null
+++ b/02. Promise的链式调用/1.js
@@ -0,0 +1,5 @@
+new Promise((resolve, reject) => {
+ reject(new Error('abc'));
+}).catch((err) => {
+ console.log('失败了!!', err);
+});
diff --git a/02. Promise的链式调用/2.js b/02. Promise的链式调用/2.js
new file mode 100644
index 0000000..35831ca
--- /dev/null
+++ b/02. Promise的链式调用/2.js
@@ -0,0 +1,12 @@
+const pro1 = new Promise((resolve, reject) => {
+ console.log('学习');
+ resolve();
+});
+
+const pro2 = pro1.then(() => {
+ return new Promise((resolve, reject) => {});
+});
+
+setTimeout(() => {
+ console.log(pro2);
+}, 1000);
diff --git a/02. Promise的链式调用/3.js b/02. Promise的链式调用/3.js
new file mode 100644
index 0000000..12d4ffa
--- /dev/null
+++ b/02. Promise的链式调用/3.js
@@ -0,0 +1,52 @@
+// 向某位女生发送一则表白短信
+// name: 女神的姓名
+// 返回:Promise
+function sendMessage(name) {
+ return new Promise((resolve, reject) => {
+ // 模拟 发送表白短信
+ console.log(
+ `邓哥 -> ${name}:最近有谣言说我喜欢你,我要澄清一下,那不是谣言😘`
+ );
+ console.log(`等待${name}回复......`);
+ // 模拟 女神回复需要一段时间
+ setTimeout(() => {
+ // 模拟 有10%的几率成功
+ if (Math.random() <= 0.3) {
+ // 成功,调用 onFuffiled,并传递女神的回复
+ resolve(`${name} -> 邓哥:我是九,你是三,除了你还是你😘`);
+ } else {
+ // 失败,调用 onRejected,并传递女神的回复
+ reject(`${name} -> 邓哥:你是个好人😜`);
+ }
+ }, 1000);
+ });
+}
+
+sendMessage('李建国')
+ .catch((reply) => {
+ // 失败,继续
+ console.log(reply);
+ return sendMessage('王富贵');
+ })
+ .catch((reply) => {
+ // 失败,继续
+ console.log(reply);
+ return sendMessage('周聚财');
+ })
+ .catch((reply) => {
+ // 失败,继续
+ console.log(reply);
+ return sendMessage('刘人勇');
+ })
+ .then(
+ (reply) => {
+ // 成功,结束
+ console.log(reply);
+ console.log('邓哥终于找到了自己的伴侣');
+ },
+ (reply) => {
+ // 最后一个也失败了
+ console.log(reply);
+ console.log('邓哥命犯天煞孤星,无伴终老,孤独一生');
+ }
+ );
diff --git a/02. Promise的链式调用/笔记.md b/02. Promise的链式调用/笔记.md
new file mode 100644
index 0000000..f9341a8
--- /dev/null
+++ b/02. Promise的链式调用/笔记.md
@@ -0,0 +1,103 @@
+
+
+# catch方法
+
+`.catch(onRejected)` = `.then(null, onRejected)`
+
+# 链式调用
+
+
+
+1. then方法必定会返回一个新的Promise
+
+ 可理解为`后续处理也是一个任务`
+
+2. 新任务的状态取决于后续处理:
+
+ - 若没有相关的后续处理,新任务的状态和前任务一致,数据为前任务的数据
+
+ - 若有后续处理但还未执行,新任务挂起。
+ - 若后续处理执行了,则根据后续处理的情况确定新任务的状态
+ - 后续处理执行无错,新任务的状态为完成,数据为后续处理的返回值
+ - 后续处理执行有错,新任务的状态为失败,数据为异常对象
+ - 后续执行后返回的是一个任务对象,新任务的状态和数据与该任务对象一致
+
+由于链式任务的存在,异步代码拥有了更强的表达力
+
+```js
+// 常见任务处理代码
+
+/*
+ * 任务成功后,执行处理1,失败则执行处理2
+ */
+pro.then(处理1).catch(处理2)
+
+/*
+ * 任务成功后,依次执行处理1、处理2
+ */
+pro.then(处理1).then(处理2)
+
+/*
+ * 任务成功后,依次执行处理1、处理2,若任务失败或前面的处理有错,执行处理3
+ */
+pro.then(处理1).then(处理2).catch(处理3)
+```
+
+# 邓哥的解决方案
+
+```js
+// 向某位女生发送一则表白短信
+// name: 女神的姓名
+// onFulffiled: 成功后的回调
+// onRejected: 失败后的回调
+function sendMessage(name) {
+ return new Promise((resolve, reject) => {
+ // 模拟 发送表白短信
+ console.log(
+ `邓哥 -> ${name}:最近有谣言说我喜欢你,我要澄清一下,那不是谣言😘`
+ );
+ console.log(`等待${name}回复......`);
+ // 模拟 女神回复需要一段时间
+ setTimeout(() => {
+ // 模拟 有10%的几率成功
+ if (Math.random() <= 0.1) {
+ // 成功,调用 onFuffiled,并传递女神的回复
+ resolve(`${name} -> 邓哥:我是九,你是三,除了你还是你😘`);
+ } else {
+ // 失败,调用 onRejected,并传递女神的回复
+ reject(`${name} -> 邓哥:你是个好人😜`);
+ }
+ }, 1000);
+ });
+}
+
+sendMessage('李建国')
+ .catch((reply) => {
+ // 失败,继续
+ console.log(reply);
+ return sendMessage('王富贵');
+ })
+ .catch((reply) => {
+ // 失败,继续
+ console.log(reply);
+ return sendMessage('周聚财');
+ })
+ .catch((reply) => {
+ // 失败,继续
+ console.log(reply);
+ return sendMessage('刘人勇');
+ })
+ .then(
+ (reply) => {
+ // 成功,结束
+ console.log(reply);
+ console.log('邓哥终于找到了自己的伴侣');
+ },
+ (reply) => {
+ // 最后一个也失败了
+ console.log(reply);
+ console.log('邓哥命犯天煞孤星,无伴终老,孤独一生');
+ }
+ );
+```
+
diff --git a/02. Promise的链式调用/练习题.1/p1.js b/02. Promise的链式调用/练习题.1/p1.js
new file mode 100644
index 0000000..8aa39b1
--- /dev/null
+++ b/02. Promise的链式调用/练习题.1/p1.js
@@ -0,0 +1,14 @@
+// 下面代码的输出结果是什么
+
+new Promise((resolve, reject) => {
+ setTimeout(() => {
+ resolve(1);
+ }, 1000);
+})
+ .then((data) => {
+ throw 3;
+ return data + 1;
+ })
+ .then((data) => {
+ console.log(data);
+ });
diff --git a/02. Promise的链式调用/练习题.1/p2.js b/02. Promise的链式调用/练习题.1/p2.js
new file mode 100644
index 0000000..0aa574b
--- /dev/null
+++ b/02. Promise的链式调用/练习题.1/p2.js
@@ -0,0 +1,19 @@
+// 下面代码的输出结果是什么
+
+const pro = new Promise((resolve, reject) => {
+ resolve(1);
+})
+ .then((res) => {
+ console.log(res);
+ return 2;
+ })
+ .catch((err) => {
+ return 3;
+ })
+ .then((res) => {
+ console.log(res);
+ });
+
+setTimeout(() => {
+ console.log(pro);
+}, 1000);
diff --git a/02. Promise的链式调用/练习题.1/p3.js b/02. Promise的链式调用/练习题.1/p3.js
new file mode 100644
index 0000000..372ecda
--- /dev/null
+++ b/02. Promise的链式调用/练习题.1/p3.js
@@ -0,0 +1,19 @@
+// 下面代码的输出结果是什么
+
+const pro = new Promise((resolve, reject) => {
+ resolve();
+})
+ .then((res) => {
+ console.log(res.toString()); // 报错
+ return 2;
+ })
+ .catch((err) => {
+ return 3;
+ })
+ .then((res) => {
+ console.log(res);
+ });
+
+setTimeout(() => {
+ console.log(pro);
+}, 1000);
diff --git a/02. Promise的链式调用/练习题.1/p4.js b/02. Promise的链式调用/练习题.1/p4.js
new file mode 100644
index 0000000..27e61d1
--- /dev/null
+++ b/02. Promise的链式调用/练习题.1/p4.js
@@ -0,0 +1,16 @@
+// 下面代码的输出结果是什么
+
+new Promise((resolve, reject) => {
+ resolve(1);
+})
+ .then((res) => {
+ console.log(res);
+ return new Error('2');
+ })
+ .catch((err) => {
+ throw err;
+ return 3;
+ })
+ .then((res) => {
+ console.log(res);
+ });
diff --git a/02. Promise的链式调用/练习题.1/p5.js b/02. Promise的链式调用/练习题.1/p5.js
new file mode 100644
index 0000000..7ebc06b
--- /dev/null
+++ b/02. Promise的链式调用/练习题.1/p5.js
@@ -0,0 +1,18 @@
+// 下面的代码输出什么
+
+const promise1 = new Promise((resolve, reject) => {
+ setTimeout(() => {
+ reject();
+ }, 1000);
+});
+const promise2 = promise1.catch(() => {
+ return 2;
+});
+
+console.log('promise1', promise1);
+console.log('promise2', promise2);
+
+setTimeout(() => {
+ console.log('promise1', promise1);
+ console.log('promise2', promise2);
+}, 2000);
diff --git a/02. Promise的链式调用/练习题/p1.js b/02. Promise的链式调用/练习题/p1.js
new file mode 100644
index 0000000..c77ad33
--- /dev/null
+++ b/02. Promise的链式调用/练习题/p1.js
@@ -0,0 +1,21 @@
+// 下面代码的输出结果是什么
+const pro1 = new Promise((resolve, reject) => {
+ setTimeout(() => {
+ resolve(1);
+ }, 1000);
+});
+
+const pro2 = pro1.then((data) => {
+ console.log(data);
+ return data + 1;
+});
+
+const pro3 = pro2.then((data) => {
+ console.log(data);
+});
+
+console.log(pro1, pro2, pro3);
+
+setTimeout(() => {
+ console.log(pro1, pro2, pro3);
+}, 2000);
diff --git a/02. Promise的链式调用/练习题/p2.js b/02. Promise的链式调用/练习题/p2.js
new file mode 100644
index 0000000..824ce4d
--- /dev/null
+++ b/02. Promise的链式调用/练习题/p2.js
@@ -0,0 +1,15 @@
+// 下面代码的输出结果是什么
+
+new Promise((resolve, reject) => {
+ resolve(1);
+})
+ .then((res) => {
+ console.log(res);
+ return 2;
+ })
+ .catch((err) => {
+ return 3;
+ })
+ .then((res) => {
+ console.log(res);
+ });
diff --git a/02. Promise的链式调用/练习题/p3.js b/02. Promise的链式调用/练习题/p3.js
new file mode 100644
index 0000000..b0f8dc7
--- /dev/null
+++ b/02. Promise的链式调用/练习题/p3.js
@@ -0,0 +1,15 @@
+// 下面代码的输出结果是什么
+
+new Promise((resolve, reject) => {
+ resolve();
+})
+ .then((res) => {
+ console.log(res.toString());
+ return 2;
+ })
+ .catch((err) => {
+ return 3;
+ })
+ .then((res) => {
+ console.log(res);
+ });
diff --git a/02. Promise的链式调用/练习题/p4.js b/02. Promise的链式调用/练习题/p4.js
new file mode 100644
index 0000000..47e70b0
--- /dev/null
+++ b/02. Promise的链式调用/练习题/p4.js
@@ -0,0 +1,16 @@
+// 下面代码的输出结果是什么
+
+new Promise((resolve, reject) => {
+ throw new Error(1);
+})
+ .then((res) => {
+ console.log(res);
+ return new Error('2');
+ })
+ .catch((err) => {
+ throw err;
+ return 3;
+ })
+ .then((res) => {
+ console.log(res);
+ });
diff --git a/02. Promise的链式调用/练习题/p5.js b/02. Promise的链式调用/练习题/p5.js
new file mode 100644
index 0000000..7ebc06b
--- /dev/null
+++ b/02. Promise的链式调用/练习题/p5.js
@@ -0,0 +1,18 @@
+// 下面的代码输出什么
+
+const promise1 = new Promise((resolve, reject) => {
+ setTimeout(() => {
+ reject();
+ }, 1000);
+});
+const promise2 = promise1.catch(() => {
+ return 2;
+});
+
+console.log('promise1', promise1);
+console.log('promise2', promise2);
+
+setTimeout(() => {
+ console.log('promise1', promise1);
+ console.log('promise2', promise2);
+}, 2000);
diff --git a/03. Promise的静态方法/1.js b/03. Promise的静态方法/1.js
new file mode 100644
index 0000000..9cc1d4f
--- /dev/null
+++ b/03. Promise的静态方法/1.js
@@ -0,0 +1,50 @@
+// 做饭
+function cook() {
+ return new Promise((resolve, reject) => {
+ console.log('邓哥打开了电饭煲');
+ setTimeout(() => {
+ if (Math.random() < 0.5) {
+ resolve('饭已ok');
+ } else {
+ reject('做饭却忘了加水,米饭变成了爆米花');
+ }
+ }, 2000);
+ });
+}
+
+// 洗衣服
+function wash() {
+ return new Promise((resolve, reject) => {
+ console.log('邓哥打开了洗衣机');
+ setTimeout(() => {
+ if (Math.random() < 0.5) {
+ resolve('衣服已经洗好');
+ } else {
+ reject('洗衣服时停水了,洗了个寂寞');
+ }
+ }, 2500);
+ });
+}
+
+// 打扫卫生
+function sweep() {
+ return new Promise((resolve, reject) => {
+ console.log('邓哥打开了扫地机器人');
+ setTimeout(() => {
+ if (Math.random() < 0.5) {
+ resolve('地板扫的非常干净');
+ } else {
+ reject('扫地机器人被哈士奇一爪掀翻了');
+ }
+ }, 3000);
+ });
+}
+
+Promise.allSettled([cook(), wash(), sweep()]).then((result) => {
+ // 处理汇总结果
+
+ const report = result
+ .map((r) => (r.status === 'fulfilled' ? r.value : r.reason))
+ .join(';');
+ console.log(report);
+});
diff --git a/03. Promise的静态方法/2.js b/03. Promise的静态方法/2.js
new file mode 100644
index 0000000..e2512be
--- /dev/null
+++ b/03. Promise的静态方法/2.js
@@ -0,0 +1,16 @@
+// const pro = new Promise((resolve, reject) => {
+// reject(1);
+// });
+// console.log(pro);
+
+const pro = Promise.race([
+ Promise.reject(1),
+ Promise.reject(2),
+ Promise.resolve(3),
+]);
+setTimeout(() => {
+ console.log(pro);
+}, 1000);
+// pro.catch((result) => {
+// console.log('失败', result.errors);
+// });
diff --git a/03. Promise的静态方法/笔记.md b/03. Promise的静态方法/笔记.md
new file mode 100644
index 0000000..5687989
--- /dev/null
+++ b/03. Promise的静态方法/笔记.md
@@ -0,0 +1,95 @@
+# 邓哥的新问题
+
+邓嫂出门时,给邓哥交待了几个任务:
+
+1. 做饭
+
+ 可交给电饭煲完成
+
+2. 洗衣服
+
+ 可交给洗衣机完成
+
+3. 打扫卫生
+
+ 可交给扫地机器人完成
+
+邓哥需要在所有任务结束后给邓嫂汇报工作,哪些成功了,哪些失败了
+
+为了最大程度的节约时间,邓哥希望这些任务同时进行,最终汇总结果统一处理
+
+
+
+每个任务可以看做是一个返回Promise的函数
+
+```js
+// 做饭
+function cook() {
+ return new Promise((resolve, reject) => {
+ console.log('邓哥打开了电饭煲');
+ setTimeout(() => {
+ if (Math.random() < 0.5) {
+ resolve('饭已ok');
+ } else {
+ reject('做饭却忘了加水,米饭变成了爆米花');
+ }
+ }, 2000);
+ });
+}
+
+// 洗衣服
+function wash() {
+ return new Promise((resolve, reject) => {
+ console.log('邓哥打开了洗衣机');
+ setTimeout(() => {
+ if (Math.random() < 0.5) {
+ resolve('衣服已经洗好');
+ } else {
+ reject('洗衣服时停水了,洗了个寂寞');
+ }
+ }, 2500);
+ });
+}
+
+// 打扫卫生
+function sweep() {
+ return new Promise((resolve, reject) => {
+ console.log('邓哥打开了扫地机器人');
+ setTimeout(() => {
+ if (Math.random() < 0.5) {
+ resolve('地板扫的非常干净');
+ } else {
+ reject('扫地机器人被哈士奇一爪掀翻了');
+ }
+ }, 3000);
+ });
+}
+
+```
+
+如何利用这三个函数实现邓哥的要求呢?
+
+# Promise的静态方法
+
+| 方法名 | 含义 |
+| ---------------------------- | ------------------------------------------------------------ |
+| Promise.resolve(data) | 直接返回一个完成状态的任务 |
+| Promise.reject(reason) | 直接返回一个拒绝状态的任务 |
+| Promise.all(任务数组) | 返回一个任务
任务数组全部成功则成功
任何一个失败则失败 |
+| Promise.any(任务数组) | 返回一个任务
任务数组任一成功则成功
任务全部失败则失败 |
+| Promise.allSettled(任务数组) | 返回一个任务
任务数组全部已决则成功
该任务不会失败 |
+| Promise.race(任务数组) | 返回一个任务
任务数组任一已决则已决,状态和其一致 |
+| | |
+
+# 邓哥的解决方案
+
+```js
+Promise.allSettled([cook(), wash(), sweep()]).then((result) => {
+ // 处理汇总结果
+ const report = result
+ .map((r) => (r.status === 'fulfilled' ? r.value : r.reason))
+ .join(';');
+ console.log(report);
+});
+```
+
diff --git a/03. Promise的静态方法/练习题/p1.js b/03. Promise的静态方法/练习题/p1.js
new file mode 100644
index 0000000..8ed6b1d
--- /dev/null
+++ b/03. Promise的静态方法/练习题/p1.js
@@ -0,0 +1,30 @@
+/**
+ * 根据页码获取学生数据,返回Promise
+ * @param {Number} page 页码
+ */
+function fetchStudents(page) {
+ return new Promise((resolve, reject) => {
+ setTimeout(() => {
+ if (Math.random() < 0.3) {
+ reject(new Error(`网络错误!获取第${page}页数据失败!`));
+ return;
+ }
+ // 模拟学生数据
+ const stus = new Array(10).fill(null).map((d, i) => ({
+ id: `NO.${(page - 1) * 10 + i + 1}`,
+ name: `姓名${(page - 1) * 10 + i + 1}`,
+ }));
+ resolve(stus);
+ }, Math.floor(Math.random() * 5000));
+ });
+}
+
+// 利用 fetchStudents 函数,完成下面的练习
+
+// 获取1-10页的学生,最终按照页码的顺序合并成一个数组,任何一页的数据获取出现错误,则任务不再继续,打印错误消息
+
+// 获取1-10页的学生,最终按照页码的顺序合并成一个数组,如果某些页码的数据获取失败,就不加入该数据即可
+
+// 获取1-10页的学生,打印最先获取到的数据,如果全部都获取失败,则打印所有的错误消息
+
+// 获取1-10页的学生,输出最先得到的结果(有结果输出结果,有错误输出错误)
diff --git a/03. Promise的静态方法/练习题参考答案/p1.html b/03. Promise的静态方法/练习题参考答案/p1.html
new file mode 100644
index 0000000..66fadbd
--- /dev/null
+++ b/03. Promise的静态方法/练习题参考答案/p1.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+ Document
+
+
+
+
+
diff --git a/03. Promise的静态方法/练习题参考答案/p1.js b/03. Promise的静态方法/练习题参考答案/p1.js
new file mode 100644
index 0000000..b2d4bf7
--- /dev/null
+++ b/03. Promise的静态方法/练习题参考答案/p1.js
@@ -0,0 +1,62 @@
+/**
+ * 根据页码获取学生数据,返回Promise
+ * @param {Number} page 页码
+ */
+function fetchStudents(page) {
+ return new Promise((resolve, reject) => {
+ setTimeout(() => {
+ if (Math.random() < 0.3) {
+ reject(new Error(`网络错误!获取第${page}页数据失败!`));
+ return;
+ }
+ // 模拟学生数据
+ const stus = new Array(10).fill(null).map((d, i) => ({
+ id: `NO.${(page - 1) * 10 + i + 1}`,
+ name: `姓名${(page - 1) * 10 + i + 1}`,
+ }));
+ resolve(stus);
+ }, Math.floor(Math.random() * 5000));
+ });
+}
+
+// 利用 fetchStudents 函数,完成下面的练习
+
+// 获取1-10页的学生,最终按照页码的顺序合并成一个数组,任何一页的数据获取出现错误,则任务不再继续,打印错误消息
+
+const proms = new Array(10).fill(1).map((it, i) => fetchStudents(i + 1));
+
+// Promise.all(proms)
+// .then((result) => {
+// console.log(result.flat());
+// })
+// .catch((err) => {
+// console.log(err);
+// });
+
+// 获取1-10页的学生,最终按照页码的顺序合并成一个数组,如果某些页码的数据获取失败,就不加入该数据即可
+// Promise.allSettled(proms).then((result) => {
+// result = result
+// .filter((r) => r.status === 'fulfilled')
+// .map((it) => it.value)
+// .flat();
+// console.log(result);
+// });
+
+// 获取1-10页的学生,打印最先获取到的数据,如果全部都获取失败,则打印所有的错误消息
+// Promise.any(proms)
+// .then((result) => {
+// console.log(result);
+// })
+// .catch((err) => {
+// console.log(err.errors);
+// });
+
+// 获取1-10页的学生,输出最先得到的结果(有结果输出结果,有错误输出错误)
+Promise.race(proms).then(
+ (result) => {
+ console.log(result);
+ },
+ (err) => {
+ console.log(err);
+ }
+);
diff --git a/04. async和await/1.js b/04. async和await/1.js
new file mode 100644
index 0000000..199761f
--- /dev/null
+++ b/04. async和await/1.js
@@ -0,0 +1,29 @@
+function delay(duration) {
+ return new Promise((resolve, reject) => {
+ setTimeout(() => {
+ reject();
+ }, duration);
+ });
+}
+
+// delay(1000).then(() => {
+// console.log('执行某个东西');
+// });
+
+(async () => {
+ try {
+ await delay(1000);
+ console.log('成功');
+ } catch (err) {
+ console.log('失败');
+ }
+})();
+
+// delay(1000).then(
+// (data) => {
+// console.log('成功');
+// },
+// (err) => {
+// console.log('失败');
+// }
+// );
diff --git a/04. async和await/2.js b/04. async和await/2.js
new file mode 100644
index 0000000..854478a
--- /dev/null
+++ b/04. async和await/2.js
@@ -0,0 +1,45 @@
+// 女神的名字数组
+const beautyGirls = ['梁平', '邱杰'];
+
+// 向某位女生发送一则表白短信
+// name: 女神的姓名
+function sendMessage(name) {
+ return new Promise((resolve, reject) => {
+ // 模拟 发送表白短信
+ console.log(
+ `邓哥 -> ${name}:最近有谣言说我喜欢你,我要澄清一下,那不是谣言😘`
+ );
+ console.log(`等待${name}回复......`);
+ // 模拟 女神回复需要一段时间
+ setTimeout(() => {
+ // 模拟 有10%的几率成功
+ if (Math.random() <= 0.1) {
+ // 成功,调用 onFuffiled,并传递女神的回复
+ resolve(`${name} -> 邓哥:我是九,你是三,除了你还是你😘`);
+ } else {
+ // 失败,调用 onRejected,并传递女神的回复
+ reject(`${name} -> 邓哥:你是个好人😜`);
+ }
+ }, 1000);
+ });
+}
+
+(async () => {
+ let isSuccess = false;
+ for (const name of beautyGirls) {
+ try {
+ const reply = await sendMessage(name);
+ console.log(reply);
+ console.log('表白成功!');
+ isSuccess = true;
+ break;
+ } catch (reply) {
+ console.log(reply);
+ console.log('表白失败');
+ }
+ }
+
+ if (!isSuccess) {
+ console.log('邓哥注定孤独一生');
+ }
+})();
diff --git a/04. async和await/笔记.md b/04. async和await/笔记.md
new file mode 100644
index 0000000..c68a530
--- /dev/null
+++ b/04. async和await/笔记.md
@@ -0,0 +1,177 @@
+
+
+# 消除回调
+
+有了Promise,异步任务就有了一种统一的处理方式
+
+有了统一的处理方式,ES官方就可以对其进一步优化
+
+ES7推出了两个关键字`async`和`await`,用于更加优雅的表达Promise
+
+## async
+
+async关键字用于修饰函数,被它修饰的函数,一定返回Promise
+
+```js
+async function method1(){
+ return 1; // 该函数的返回值是Promise完成后的数据
+}
+
+method1(); // Promise { 1 }
+
+async function method2(){
+ return Promise.resolve(1); // 若返回的是Promise,则method得到的Promise状态和其一致
+}
+
+method2(); // Promise { 1 }
+
+async function method3(){
+ throw new Error(1); // 若执行过程报错,则任务是rejected
+}
+
+method3(); // Promise { Error(1) }
+```
+
+## await
+
+`await`关键字表示等待某个Promise完成,**它必须用于`async`函数中**
+
+```js
+async function method(){
+ const n = await Promise.resolve(1);
+ console.log(n); // 1
+}
+
+// 上面的函数等同于
+function method(){
+ return new Promise((resolve, reject)=>{
+ Promise.resolve(1).then(n=>{
+ console.log(n);
+ resolve(1)
+ })
+ })
+}
+```
+
+`await`也可以等待其他数据
+
+```js
+async function method(){
+ const n = await 1; // 等同于 await Promise.resolve(1)
+}
+```
+
+如果需要针对失败的任务进行处理,可以使用`try-catch`语法
+
+```js
+async function method(){
+ try{
+ const n = await Promise.reject(123); // 这句代码将抛出异常
+ console.log('成功', n)
+ }
+ catch(err){
+ console.log('失败', err)
+ }
+}
+
+method(); // 输出: 失败 123
+```
+
+
+
+# 邓哥表白的完美解决方案
+
+邓哥的女神可不是只有4位,而是40位!
+
+为了更加方便的编写表白代码,邓哥决定把这40位女神放到一个数组中,然后利用async和await轻松完成代码
+
+```js
+// 女神的名字数组
+const beautyGirls = [
+ '梁平',
+ '邱杰',
+ '王超',
+ '冯秀兰',
+ '赖军',
+ '顾强',
+ '戴敏',
+ '吕涛',
+ '冯静',
+ '蔡明',
+ '廖磊',
+ '冯洋',
+ '韩杰',
+ '江涛',
+ '文艳',
+ '杜秀英',
+ '丁艳',
+ '邓静',
+ '江刚',
+ '乔刚',
+ '史平',
+ '康娜',
+ '袁磊',
+ '龙秀英',
+ '姚静',
+ '潘娜',
+ '萧磊',
+ '邵勇',
+ '李芳',
+ '谭芳',
+ '夏秀英',
+ '程娜',
+ '武杰',
+ '崔军',
+ '廖勇',
+ '崔强',
+ '康秀英',
+ '余磊',
+ '邵勇',
+ '贺涛',
+];
+
+// 向某位女生发送一则表白短信
+// name: 女神的姓名
+function sendMessage(name) {
+ return new Promise((resolve, reject) => {
+ // 模拟 发送表白短信
+ console.log(
+ `邓哥 -> ${name}:最近有谣言说我喜欢你,我要澄清一下,那不是谣言😘`
+ );
+ console.log(`等待${name}回复......`);
+ // 模拟 女神回复需要一段时间
+ setTimeout(() => {
+ // 模拟 有10%的几率成功
+ if (Math.random() <= 0.1) {
+ // 成功,调用 onFuffiled,并传递女神的回复
+ resolve(`${name} -> 邓哥:我是九,你是三,除了你还是你😘`);
+ } else {
+ // 失败,调用 onRejected,并传递女神的回复
+ reject(`${name} -> 邓哥:你是个好人😜`);
+ }
+ }, 1000);
+ });
+}
+
+// 批量表白的程序
+async function proposal() {
+ let isSuccess = false;
+ for (const girl of beautyGirls) {
+ try {
+ const reply = await sendMessage(girl);
+ console.log(reply);
+ console.log('表白成功!');
+ isSuccess = true;
+ break;
+ } catch (reply) {
+ console.log(reply);
+ console.log('表白失败');
+ }
+ }
+ if (!isSuccess) {
+ console.log('邓哥注定孤独一生');
+ }
+}
+proposal();
+```
+
diff --git a/04. async和await/练习题/p1.html b/04. async和await/练习题/p1.html
new file mode 100644
index 0000000..d169e85
--- /dev/null
+++ b/04. async和await/练习题/p1.html
@@ -0,0 +1,13 @@
+
+
+
diff --git a/04. async和await/练习题/p2.js b/04. async和await/练习题/p2.js
new file mode 100644
index 0000000..8950bb2
--- /dev/null
+++ b/04. async和await/练习题/p2.js
@@ -0,0 +1,7 @@
+// 完成delay函数
+// 该函数可以等待一段指定的时间
+// 返回Promise
+function delay(duration) {}
+
+// 利用delay函数,等待3次,每次等待1秒,每次等待完成后输出ok
+// 等待1秒->ok->等待1秒->ok->等待1秒->ok
diff --git a/04. async和await/练习题参考答案/p1.html b/04. async和await/练习题参考答案/p1.html
new file mode 100644
index 0000000..1d4e7ff
--- /dev/null
+++ b/04. async和await/练习题参考答案/p1.html
@@ -0,0 +1,19 @@
+
+
+
diff --git a/04. async和await/练习题参考答案/p2.js b/04. async和await/练习题参考答案/p2.js
new file mode 100644
index 0000000..f2f54d0
--- /dev/null
+++ b/04. async和await/练习题参考答案/p2.js
@@ -0,0 +1,33 @@
+// 完成delay函数
+// 该函数可以等待一段指定的时间
+// 返回Promise
+function delay(duration) {
+ return new Promise((resolve, reject) => {
+ setTimeout(() => {
+ resolve();
+ }, duration);
+ });
+}
+
+// 利用delay函数,等待3次,每次等待1秒,每次等待完成后输出ok
+// 等待1秒->ok->等待1秒->ok->等待1秒->ok
+
+(async () => {
+ for (let i = 0; i < 3; i++) {
+ await delay(1000);
+ console.log('ok');
+ }
+})();
+
+// delay(1000)
+// .then(() => {
+// console.log('ok');
+// return delay(1000);
+// })
+// .then(() => {
+// console.log('ok');
+// return delay(1000);
+// })
+// .then(() => {
+// console.log('ok');
+// });
diff --git a/05. Promise相关面试题/1.js b/05. Promise相关面试题/1.js
new file mode 100644
index 0000000..df5a995
--- /dev/null
+++ b/05. Promise相关面试题/1.js
@@ -0,0 +1,11 @@
+const promise = new Promise((resolve, reject) => {
+ console.log(1);
+ resolve();
+ console.log(2);
+});
+
+promise.then(() => {
+ console.log(3);
+});
+
+console.log(4);
diff --git a/05. Promise相关面试题/2.js b/05. Promise相关面试题/2.js
new file mode 100644
index 0000000..2af03b7
--- /dev/null
+++ b/05. Promise相关面试题/2.js
@@ -0,0 +1,14 @@
+setTimeout(() => {
+ console.log(1);
+});
+
+const promise = new Promise((resolve, reject) => {
+ console.log(2);
+ resolve();
+});
+
+promise.then(() => {
+ console.log(3);
+});
+
+console.log(4);
diff --git a/05. Promise相关面试题/3.js b/05. Promise相关面试题/3.js
new file mode 100644
index 0000000..b572e96
--- /dev/null
+++ b/05. Promise相关面试题/3.js
@@ -0,0 +1,16 @@
+const promise1 = new Promise((resolve, reject) => {
+ setTimeout(() => {
+ reject();
+ }, 1000);
+});
+const promise2 = promise1.catch(() => {
+ return 2;
+});
+
+console.log('promise1', promise1);
+console.log('promise2', promise2);
+
+setTimeout(() => {
+ console.log('promise1', promise1);
+ console.log('promise2', promise2);
+}, 2000);
diff --git a/05. Promise相关面试题/4.js b/05. Promise相关面试题/4.js
new file mode 100644
index 0000000..453f854
--- /dev/null
+++ b/05. Promise相关面试题/4.js
@@ -0,0 +1,14 @@
+async function m() {
+ console.log(0);
+ const n = await 1;
+ console.log(n);
+}
+
+// function m() {
+// return Promise.resolve(1).then((n) => {
+// console.log(n);
+// });
+// }
+
+m();
+console.log(2);
diff --git a/05. Promise相关面试题/5.js b/05. Promise相关面试题/5.js
new file mode 100644
index 0000000..88bd44b
--- /dev/null
+++ b/05. Promise相关面试题/5.js
@@ -0,0 +1,12 @@
+async function m() {
+ console.log(0);
+ const n = await 1;
+ console.log(n);
+}
+
+(async () => {
+ await m();
+ console.log(2);
+})();
+
+console.log(3);
diff --git a/05. Promise相关面试题/6.js b/05. Promise相关面试题/6.js
new file mode 100644
index 0000000..1c4f9f2
--- /dev/null
+++ b/05. Promise相关面试题/6.js
@@ -0,0 +1,23 @@
+async function m1() {
+ return 1;
+}
+
+async function m2() {
+ const n = await m1();
+ console.log(n);
+ return 2;
+}
+
+async function m3() {
+ const n = m2();
+ console.log(n);
+ return 3;
+}
+
+m3().then((n) => {
+ console.log(n);
+});
+
+m3();
+
+console.log(4);
diff --git a/05. Promise相关面试题/7.js b/05. Promise相关面试题/7.js
new file mode 100644
index 0000000..507f0ed
--- /dev/null
+++ b/05. Promise相关面试题/7.js
@@ -0,0 +1 @@
+Promise.resolve(1).then(2).then(Promise.resolve(3)).then(console.log);
diff --git a/05. Promise相关面试题/8.js b/05. Promise相关面试题/8.js
new file mode 100644
index 0000000..09cff15
--- /dev/null
+++ b/05. Promise相关面试题/8.js
@@ -0,0 +1,28 @@
+var a;
+var b = new Promise((resolve, reject) => {
+ console.log('promise1');
+ setTimeout(() => {
+ resolve();
+ }, 1000);
+})
+ .then(() => {
+ console.log('promise2');
+ })
+ .then(() => {
+ console.log('promise3');
+ })
+ .then(() => {
+ console.log('promise4');
+ });
+
+a = new Promise(async (resolve, reject) => {
+ console.log(a);
+ await b;
+ console.log(a);
+ console.log('after1');
+ await a;
+ resolve(true);
+ console.log('after2');
+});
+
+console.log('end');
diff --git a/05. Promise相关面试题/9.js b/05. Promise相关面试题/9.js
new file mode 100644
index 0000000..0fac89d
--- /dev/null
+++ b/05. Promise相关面试题/9.js
@@ -0,0 +1,24 @@
+async function async1() {
+ console.log('async1 start');
+ await async2();
+ console.log('async1 end');
+}
+async function async2() {
+ console.log('async2');
+}
+
+console.log('script start');
+
+setTimeout(function () {
+ console.log('setTimeout');
+}, 0);
+
+async1();
+
+new Promise(function (resolve) {
+ console.log('promise1');
+ resolve();
+}).then(function () {
+ console.log('promise2');
+});
+console.log('script end');
diff --git a/05. Promise相关面试题/笔记.md b/05. Promise相关面试题/笔记.md
new file mode 100644
index 0000000..dafb9cf
--- /dev/null
+++ b/05. Promise相关面试题/笔记.md
@@ -0,0 +1,311 @@
+# 面试题考点
+
+## Promise的基本概念
+
+
+
+## 链式调用规则
+
+
+
+
+
+1. then方法必定会返回一个新的Promise
+
+ 可理解为`后续处理也是一个任务`
+
+2. 新任务的状态取决于后续处理:
+
+ - 若没有相关的后续处理,新任务的状态和前任务一致,数据为前任务的数据
+
+ - 若有后续处理但还未执行,新任务挂起。
+ - 若后续处理执行了,则根据后续处理的情况确定新任务的状态
+ - 后续处理执行无错,新任务的状态为完成,数据为后续处理的返回值
+ - 后续处理执行有错,新任务的状态为失败,数据为异常对象
+ - 后续执行后返回的是一个任务对象,新任务的状态和数据与该任务对象一致
+
+## Promise的静态方法
+
+| 方法名 | 含义 |
+| ---------------------------- | ------------------------------------------------------------ |
+| Promise.resolve(data) | 直接返回一个完成状态的任务 |
+| Promise.reject(reason) | 直接返回一个拒绝状态的任务 |
+| Promise.all(任务数组) | 返回一个任务
任务数组全部成功则成功
任何一个失败则失败 |
+| Promise.any(任务数组) | 返回一个任务
任务数组任一成功则成功
任务全部失败则失败 |
+| Promise.allSettled(任务数组) | 返回一个任务
任务数组全部已决则成功
该任务不会失败 |
+| Promise.race(任务数组) | 返回一个任务
任务数组任一已决则已决,状态和其一致 |
+| | |
+
+## async和await
+
+有了Promise,异步任务就有了一种统一的处理方式
+
+有了统一的处理方式,ES官方就可以对其进一步优化
+
+ES7推出了两个关键字`async`和`await`,用于更加优雅的表达Promise
+
+### async
+
+async关键字用于修饰函数,被它修饰的函数,一定返回Promise
+
+```js
+async function method1(){
+ return 1; // 该函数的返回值是Promise完成后的数据
+}
+
+method1(); // Promise { 1 }
+
+async function method2(){
+ return Promise.resolve(1); // 若返回的是Promise,则method得到的Promise状态和其一致
+}
+
+method2(); // Promise { 1 }
+
+async function method3(){
+ throw new Error(1); // 若执行过程报错,则任务是rejected
+}
+
+method3(); // Promise { Error(1) }
+```
+
+### await
+
+`await`关键字表示等待某个Promise完成,**它必须用于`async`函数中**
+
+```js
+async function method(){
+ const n = await Promise.resolve(1);
+ console.log(n); // 1
+}
+
+// 上面的函数等同于
+function method(){
+ return new Promise((resolve, reject)=>{
+ Promise.resolve(1).then(n=>{
+ console.log(n);
+ resolve(1)
+ })
+ })
+}
+```
+
+`await`也可以等待其他数据
+
+```js
+async function method(){
+ const n = await 1; // 等同于 await Promise.resolve(1)
+}
+```
+
+如果需要针对失败的任务进行处理,可以使用`try-catch`语法
+
+```js
+async function method(){
+ try{
+ const n = await Promise.reject(123); // 这句代码将抛出异常
+ console.log('成功', n)
+ }
+ catch(err){
+ console.log('失败', err)
+ }
+}
+
+method(); // 输出: 失败 123
+```
+
+## 事件循环
+
+根据目前所学,进入事件队列的函数有以下几种:
+
+- `setTimeout`的回调,宏任务(macro task)
+- `setInterval`的回调,宏任务(macro task)
+- Promise的`then`函数回调,**微任务**(micro task)
+- `requestAnimationFrame`的回调,宏任务(macro task)
+- 事件处理函数,宏任务(macro task)
+
+# 面试题
+
+1. 下面代码的输出结果是什么
+
+ ```js
+ const promise = new Promise((resolve, reject) => {
+ console.log(1);
+ resolve();
+ console.log(2);
+ })
+
+ promise.then(() => {
+ console.log(3);
+ })
+
+ console.log(4);
+ ```
+
+2. 下面代码的输出结果是什么
+
+ ```js
+ const promise = new Promise((resolve, reject) => {
+ console.log(1);
+ setTimeout(()=>{
+ console.log(2)
+ resolve();
+ console.log(3);
+ })
+ })
+
+ promise.then(() => {
+ console.log(4);
+ })
+
+ console.log(5);
+ ```
+
+3. 下面代码的输出结果是什么
+
+ ```js
+ const promise1 = new Promise((resolve, reject) => {
+ setTimeout(() => {
+ resolve()
+ }, 1000)
+ })
+ const promise2 = promise1.catch(() => {
+ return 2;
+ })
+
+ console.log('promise1', promise1)
+ console.log('promise2', promise2)
+
+ setTimeout(() => {
+ console.log('promise1', promise1)
+ console.log('promise2', promise2)
+ }, 2000)
+ ```
+
+4. 下面代码的输出结果是什么
+
+ ```js
+ async function m(){
+ const n = await 1;
+ console.log(n);
+ }
+
+ m();
+ console.log(2);
+ ```
+
+5. 下面代码的输出结果是什么
+
+ ```js
+ async function m(){
+ const n = await 1;
+ console.log(n);
+ }
+
+ (async ()=>{
+ await m();
+ console.log(2);
+ })();
+
+ console.log(3);
+ ```
+
+
+
+6. 下面代码的输出结果是什么
+
+ ```js
+ async function m1(){
+ return 1;
+ }
+
+ async function m2(){
+ const n = await m1();
+ console.log(n)
+ return 2;
+ }
+
+ async function m3(){
+ const n = m2();
+ console.log(n);
+ return 3;
+ }
+
+ m3().then(n=>{
+ console.log(n);
+ });
+
+ m3();
+
+ console.log(4);
+ ```
+
+7. 下面代码的输出结果是什么
+
+ ```js
+ Promise.resolve(1)
+ .then(2)
+ .then(Promise.resolve(3))
+ .then(console.log)
+ ```
+
+8. 下面代码的输出结果是什么
+
+ ```js
+ var a;
+ var b = new Promise((resolve, reject) => {
+ console.log('promise1');
+ setTimeout(()=>{
+ resolve();
+ }, 1000);
+ }).then(() => {
+ console.log('promise2');
+ }).then(() => {
+ console.log('promise3');
+ }).then(() => {
+ console.log('promise4');
+ });
+
+ a = new Promise(async (resolve, reject) => {
+ console.log(a);
+ await b;
+ console.log(a);
+ console.log('after1');
+ await a
+ resolve(true);
+ console.log('after2');
+ });
+
+ console.log('end');
+ ```
+
+9. 下面代码的输出结果是什么
+
+ ```js
+ async function async1() {
+ console.log('async1 start');
+ await async2();
+ console.log('async1 end');
+ }
+ async function async2() {
+ console.log('async2');
+ }
+
+ console.log('script start');
+
+ setTimeout(function() {
+ console.log('setTimeout');
+ }, 0)
+
+ async1();
+
+ new Promise(function(resolve) {
+ console.log('promise1');
+ resolve();
+ }).then(function() {
+ console.log('promise2');
+ });
+ console.log('script end');
+ ```
+
+
+
diff --git a/06. 手写Promise/MyPromise.js b/06. 手写Promise/MyPromise.js
new file mode 100644
index 0000000..5c5ae5b
--- /dev/null
+++ b/06. 手写Promise/MyPromise.js
@@ -0,0 +1,287 @@
+// 记录Promise的三种状态
+const PENDING = 'pending';
+const FULFILLED = 'fulfilled';
+const REJECTED = 'rejected';
+
+/**
+ * 运行一个微队列任务
+ * 把传递的函数放到微队列中
+ * @param {Function} callback
+ */
+function runMicroTask(callback) {
+ // 判断node环境
+ // 为了避免「变量未定义」的错误,这里最好加上前缀globalThis
+ // globalThis是一个关键字,指代全局对象,浏览器环境为window,node环境为global
+ if (globalThis.process && globalThis.process.nextTick) {
+ process.nextTick(callback);
+ } else if (globalThis.MutationObserver) {
+ const p = document.createElement('p');
+ const observer = new MutationObserver(callback);
+ observer.observe(p, {
+ childList: true, // 观察该元素内部的变化
+ });
+ p.innerHTML = '1';
+ } else {
+ setTimeout(callback, 0);
+ }
+}
+
+/**
+ * 判断一个数据是否是Promise对象
+ * @param {any} obj
+ * @returns
+ */
+function isPromise(obj) {
+ return !!(obj && typeof obj === 'object' && typeof obj.then === 'function');
+}
+
+class MyPromise {
+ /**
+ * 创建一个Promise
+ * @param {Function} executor 任务执行器,立即执行
+ */
+ constructor(executor) {
+ this._state = PENDING; // 状态
+ this._value = undefined; // 数据
+ this._handlers = []; // 处理函数形成的队列
+ try {
+ executor(this._resolve.bind(this), this._reject.bind(this));
+ } catch (error) {
+ this._reject(error);
+ console.error(error);
+ }
+ }
+
+ /**
+ * 向处理队列中添加一个函数
+ * @param {Function} executor 添加的函数
+ * @param {String} state 该函数什么状态下执行
+ * @param {Function} resolve 让then函数返回的Promise成功
+ * @param {Function} reject 让then函数返回的Promise失败
+ */
+ _pushHandler(executor, state, resolve, reject) {
+ this._handlers.push({
+ executor,
+ state,
+ resolve,
+ reject,
+ });
+ }
+
+ /**
+ * 根据实际情况,执行队列
+ */
+ _runHandlers() {
+ if (this._state === PENDING) {
+ // 目前任务仍在挂起
+ return;
+ }
+ while (this._handlers[0]) {
+ const handler = this._handlers[0];
+ this._runOneHandler(handler);
+ this._handlers.shift();
+ }
+ }
+
+ /**
+ * 处理一个handler
+ * @param {Object} handler
+ */
+ _runOneHandler({ executor, state, resolve, reject }) {
+ runMicroTask(() => {
+ if (this._state !== state) {
+ // 状态不一致,不处理
+ return;
+ }
+
+ if (typeof executor !== 'function') {
+ // 传递后续处理并非一个函数
+ this._state === FULFILLED ? resolve(this._value) : reject(this._value);
+ return;
+ }
+ try {
+ const result = executor(this._value);
+ if (isPromise(result)) {
+ result.then(resolve, reject);
+ } else {
+ resolve(result);
+ }
+ } catch (error) {
+ reject(error);
+ console.error(error);
+ }
+ });
+ }
+
+ /**
+ * Promise A+规范的then
+ * @param {Function} onFulfilled
+ * @param {Function} onRejected
+ */
+ then(onFulfilled, onRejected) {
+ return new MyPromise((resolve, reject) => {
+ this._pushHandler(onFulfilled, FULFILLED, resolve, reject);
+ this._pushHandler(onRejected, REJECTED, resolve, reject);
+ this._runHandlers(); // 执行队列
+ });
+ }
+
+ /**
+ * 仅处理失败的场景
+ * @param {Function} onRejected
+ */
+ catch(onRejected) {
+ return this.then(null, onRejected);
+ }
+
+ /**
+ * 无论成功还是失败都会执行回调
+ * @param {Function} onSettled
+ */
+ finally(onSettled) {
+ return this.then(
+ (data) => {
+ onSettled();
+ return data;
+ },
+ (reason) => {
+ onSettled();
+ throw reason;
+ }
+ );
+ }
+
+ /**
+ * 更改任务状态
+ * @param {String} newState 新状态
+ * @param {any} value 相关数据
+ */
+ _changeState(newState, value) {
+ if (this._state !== PENDING) {
+ // 目前状态已经更改
+ return;
+ }
+ this._state = newState;
+ this._value = value;
+ this._runHandlers(); // 状态变化,执行队列
+ }
+
+ /**
+ * 标记当前任务完成
+ * @param {any} data 任务完成的相关数据
+ */
+ _resolve(data) {
+ this._changeState(FULFILLED, data);
+ }
+
+ /**
+ * 标记当前任务失败
+ * @param {any} reason 任务失败的相关数据
+ */
+ _reject(reason) {
+ this._changeState(REJECTED, reason);
+ }
+
+ /**
+ * 返回一个已完成的Promise
+ * 特殊情况:
+ * 1. 传递的data本身就是ES6的Promise对象
+ * 2. 传递的data是PromiseLike(Promise A+),返回新的Promise,状态和其保持一致即可
+ * @param {any} data
+ */
+ static resolve(data) {
+ if (data instanceof MyPromise) {
+ return data;
+ }
+ return new MyPromise((resolve, reject) => {
+ if (isPromise(data)) {
+ data.then(resolve, reject);
+ } else {
+ resolve(data);
+ }
+ });
+ }
+
+ /**
+ * 得到一个被拒绝的Promise
+ * @param {any}} reason
+ */
+ static reject(reason) {
+ return new MyPromise((resolve, reject) => {
+ reject(reason);
+ });
+ }
+
+ /**
+ * 得到一个新的Promise
+ * 该Promise的状态取决于proms的执行
+ * proms是一个迭代器,包含多个Promise
+ * 全部Promise成功,则返回的Promise成功,数据为所有Promise成功的数据,并且顺序是按照传入的顺序排列
+ * 只要有一个Promise失败,则返回的Promise失败,原因是第一个失败的Promise的原因
+ * @param {iterator} proms
+ */
+ static all(proms) {
+ return new MyPromise((resolve, reject) => {
+ try {
+ const results = [];
+ let count = 0; // Promise的总数
+ let fulfilledCount = 0; // 已完成的数量
+ for (const p of proms) {
+ let i = count;
+ count++;
+ MyPromise.resolve(p).then((data) => {
+ fulfilledCount++;
+ results[i] = data;
+ if (fulfilledCount === count) {
+ // 当前是最后一个Promise完成了
+ resolve(results);
+ }
+ }, reject);
+ }
+ if (count === 0) {
+ resolve(results);
+ }
+ } catch (error) {
+ reject(error);
+ console.error(error);
+ }
+ });
+ }
+
+ /**
+ * 等待所有的Promise有结果之后
+ * 该方法返回的Promise完成
+ * 并且按照顺序将所有结果汇总
+ * @param {iterator} proms
+ */
+ static allSettled(proms) {
+ const ps = [];
+ for (const p of proms) {
+ ps.push(
+ MyPromise.resolve(p).then(
+ (value) => ({
+ status: FULFILLED,
+ value,
+ }),
+ (reason) => ({
+ status: REJECTED,
+ reason,
+ })
+ )
+ );
+ }
+ return MyPromise.all(ps);
+ }
+
+ /**
+ * 返回的Promise与第一个有结果的一致
+ * @param {iterator} proms
+ */
+ static race(proms) {
+ return new MyPromise((resolve, reject) => {
+ for (const p of proms) {
+ MyPromise.resolve(p).then(resolve, reject);
+ }
+ });
+ }
+}
diff --git a/06. 手写Promise/说明.md b/06. 手写Promise/说明.md
new file mode 100644
index 0000000..c91a676
--- /dev/null
+++ b/06. 手写Promise/说明.md
@@ -0,0 +1,3 @@
+手写 Promise 课程资料,仅提供最终的完整代码
+
+至于每节课的代码,请同学们理解视频课程内容,然后自行手写,以达到最好的学习效果
diff --git a/知识图谱.drawio b/知识图谱.drawio
new file mode 100644
index 0000000..2400597
--- /dev/null
+++ b/知识图谱.drawio
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file