Browse Source

async await

usuiforhe 3 years ago
parent
commit
e6a08074ca
1 changed files with 298 additions and 2 deletions
  1. 298 2
      TS/JaveScript.md

+ 298 - 2
TS/JaveScript.md

@@ -3,7 +3,7 @@
  * @Autor: LC
  * @Date: 2022-01-20 10:45:55
  * @LastEditors: Please set LastEditors
- * @LastEditTime: 2022-02-05 18:03:39
+ * @LastEditTime: 2022-02-05 23:06:32
  * @Description: file content
 -->
 # JavaScipt语法
@@ -2752,7 +2752,7 @@ new Promise((resolve, reject) => {
 - `resolve()`函数的参数
   1. 普通的值和对象(就当普通的函数传递一样使用,会从`Pedning`转到`fulfilled`状态)
   2. 传入一个`Promise`对象(当前`Promise`的状态会由传入的`Promise`的状态来决定,看下面代码 **例子1**)
-  3. 入一个对象,并且对象有`then`方法,那么会执行该`then`方法,并且由`then`方法决定后续状态(下面代码 **例子2**)
+  3. 入一个对象,并且对象有`then`方法,那么会执行该`then`方法,并且由`then`方法决定后续状态(下面代码 **例子2**)
 
 ```javascript
 // 例子 1
@@ -3469,3 +3469,299 @@ for (let s of c1) {
 
 > 通过生成器,简化迭代器的写法
 
+### 异步函数的处理方法(前面Promise)
+
+- 需求:三次请求,请求就是返回原字符串,然后分别往初始字符串后添加"aa", "bb"
+
+> 模拟:通过 用户ID->用户信息->部门信息->其他信息,这种链式请求
+
+```javascript
+function requestData(url){
+    return new Promise((resolve, reject) => {
+        setTimeout(() => {
+            resolve(url);
+        }, 1000);
+    })
+}
+
+// 方案1
+requestData("test").then(res => {
+    requestData(res + "aa").then(res => {
+        requestData(res + "bb").then(res => {
+            console.log(res);
+        })
+    })
+})
+
+// 方案2
+requestData("test").then(res=>{
+    return requestData(res + "aa")
+}, () => {}).then(res => {
+    return requestData(res + "bb")
+}, () => {}).then(res => {
+    console.log(res);
+}, () => {});
+
+// 方案3 Promise + generator
+function* getData() {
+    let val1 = yield requestData("test");
+    let val2 = yield requestData(val1 + "aa");
+    let val3 = yield requestData(val2 + "bb");
+    console.log(val3);
+}
+
+const generator = getData();
+// generator返回的是对象,它的value是Promise对象
+generator.next().value.then(res => {
+    generator.next(res).value.then(res => {
+        generator.next(res).value.then(res => {
+            generator.next(res);
+        })
+    })
+})
+
+// 方案4 (方案3的升级版)
+function execGeneractor(generatorFunc) {
+    const generactor = generatorFunc();
+
+    function exec(res) {
+        const result = generactor.next(res);
+        if (result.done === true) {
+            return result.value;
+        }
+        result.value.then(res => {
+            exec(res);
+        });
+    }
+    exec();
+}
+
+execGeneractor(getData);
+
+// 方案5
+async function getData(){
+    const res1 = await requestData("test");
+    const res2 = await requestData(res1 + "aa");
+    const res3 = await requestData(res2 + "bb");
+    console.log(res3);
+}
+getData();
+```
+
+- 方案1:嵌套,回调套回调
+- 方案2:没有回调套回调,利用Promise的then的特性,可读性差
+- 方案3:利用生成器,但是回调嵌套了
+- 方案4:利用生成器、递归,自动执行代码到结束为止,并且扩展性强
+- 方案5:`async` + `await`组合(`Promise`和生成器组合的语法糖)
+
+## async-await-事件循环(ES8)
+
+### 异步函数 async function
+
+- `async`关键字用于声明一个异步函数
+  - `async`是`asynchronous`单词的缩写,异步、非同步
+  - `sync`是`synchronous`单词的缩写,同步,同时
+
+```javascript
+async function foo1(){
+
+}
+
+const foo2 = async() => {
+    
+}
+
+class Foo{
+    async foo3(){
+
+    }
+}
+```
+
+> 异步函数的写法
+
+**异步函数**的代码在函数中没有特殊内容时,函数的执行流程跟普通函数是一样的  
+
+```javascript
+async function foo(){
+    console.log("1");
+    console.log("2");
+    console.log("3");
+    console.log("4");
+}
+
+foo();  // 1 2 3 4
+```
+
+**异步函数**的返回值一定是`Promise`(没有返回值也是Promise)  
+
+```javascript
+// 返回普通值
+async function foo(){
+    console.log("start...");
+    console.log("mid code...");
+    console.log("end...");
+    // 没有返回值时 默认return undefined
+    return 123;
+}
+
+// 返回带then方法对象
+async function foo1(){
+    console.log("start...");
+    console.log("mid code...");
+    console.log("end...");
+    // 没有返回值时 默认return undefined
+    return {
+        then : function(resolve, reject){
+            resolve("hhh");
+        }
+    };
+}
+
+// 返回Promise
+async function foo2(){
+    console.log("start...");
+    console.log("mid code...");
+    console.log("end...");
+    // 没有返回值时 默认return undefined
+    return new Promise((resolve, reject) => {
+        setTimeout(() => {
+            resolve("www");
+        }, 1000);
+    });
+}
+
+const promise = foo();
+promise.then(res => {
+    console.log("promise run code", res);
+})
+const promise1 = foo1();
+promise1.then(res => {
+    console.log("promise1 run code", res);
+})
+const promise2 = foo2();
+promise2.then(res => {
+    console.log("promise run resolve", res);
+}, (err) => {
+    console.log("promise run err", err);
+});
+```
+
+> `promise`执行的时机是`foo()`函数return的时候  
+> 如果**异步函数**返回的是含有`then`方法的对象,跟`Promise`返回含有`then`方法对象一样(`resolve()函数的参数`<=搜索关键字)  
+> 如果**异步函数**返回值是`Promise`,会等待`resolve`或者`reject`执行完毕才会出发`then`  
+
+-----
+
+**异步函数**的异常,会被捕获为`Promise`的`reject`的值
+
+```javascript
+async function foo2() {
+    console.log("foo2 start");
+
+    throw new Error("error message");
+
+    console.log("foo2 end");
+}
+
+foo2().catch(err => {
+    console.log(err);
+});
+
+console.log("other code...");
+```
+
+> 继续执行后续代码,打印`other code...`
+
+```javascript
+function foo1() {
+    console.log("foo2 start");
+
+    throw new Error("error message");
+
+    console.log("foo2 end");
+}
+foo1();
+console.log("other code...");
+```
+
+> 普通函数遇到异常,直接整个中断不会执行最后的输出`other code...`
+
+### await
+
+`async`函数另外一个特殊之处,就是它可以在**内部使用await关键字**,而在**普通函数中不可以使用**
+
+> await if only valid in async function  
+
+一般而言`await`后面会跟着也给**表达式**,并且返回一个`Promise`
+
+> await 表达式(Promise)
+  
+
+```javascript
+function requestData(){
+    return new Promise((resolve, reject) => {
+        setTimeout(() => {
+            resolve("1234");
+        }, 10000)
+    });
+}
+
+// await跟上表达式
+async function foo(){
+    let res = await requestData();  // 在调用resolve时给到res结果
+    console.log("-----", res);
+    console.log("-----");
+
+    let res = await requestData();  // 在调用resolve时给到res结果
+    console.log("+++++", res);
+    console.log("+++++");
+}
+foo();
+```
+
+> `await`之后的代码会等待`await`有返回值之后才会执行  
+> 可以把`await`后面的代码理解为是在`Prommise`里面`then`回调中执行的
+
+```javascript
+// await跟上其他的值
+async function foo1(){
+    const res1 = await 123;
+    console.log(res1);
+
+    const res2 = await {
+        then : function(resolve, reject) {
+            resolve(234);
+        }
+    }
+    console.log(res2);
+}
+
+foo1();
+```
+
+> `await`后面跟普通的值会立即返回  
+> 如果返回对象中含有名为`then`的`function`,会执行`then`方法,并返回`resolve`的值  
+
+```javascript
+function requestData() {
+    return new Promise((resolve, reject) => {
+        setTimeout(() => {
+            reject("1234");
+        }, 100)
+    });
+}
+
+async function foo2() {
+    const res2 = await requestData();
+    console.log(res2);
+    console.log("------------");
+}
+
+foo2().catch(err => {
+    console.log(err);
+});
+```
+
+> 如果`await`后面的`Promise`执行`reject`函数,那么整个`foo2`都会立即终止,并且触发**异步函数**的`catch`
+