From dc02aaf52496ccdb99626664a4681d203c897803 Mon Sep 17 00:00:00 2001 From: qianguyihao Date: Tue, 6 Jun 2023 21:14:11 +0800 Subject: [PATCH] =?UTF-8?q?add:=20=E7=94=A8=E7=94=9F=E6=88=90=E5=99=A8?= =?UTF-8?q?=E5=B0=81=E8=A3=85=E9=93=BE=E5=BC=8F=E8=B0=83=E7=94=A8=E3=80=81?= =?UTF-8?q?=E7=94=A8=20async=20...=20await=20=E5=B0=81=E8=A3=85=E9=93=BE?= =?UTF-8?q?=E5=BC=8F=E8=B0=83=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...76\345\274\217\350\260\203\347\224\250.md" | 82 ++++++++++++++++++- ...14\347\224\237\346\210\220\345\231\250.md" | 4 +- 2 files changed, 80 insertions(+), 6 deletions(-) diff --git "a/06-JavaScript\345\237\272\347\241\200\357\274\232\345\274\202\346\255\245\347\274\226\347\250\213/09-Promise\347\232\204\351\223\276\345\274\217\350\260\203\347\224\250.md" "b/06-JavaScript\345\237\272\347\241\200\357\274\232\345\274\202\346\255\245\347\274\226\347\250\213/09-Promise\347\232\204\351\223\276\345\274\217\350\260\203\347\224\250.md" index 72c8409b..9adb86da 100644 --- "a/06-JavaScript\345\237\272\347\241\200\357\274\232\345\274\202\346\255\245\347\274\226\347\250\213/09-Promise\347\232\204\351\223\276\345\274\217\350\260\203\347\224\250.md" +++ "b/06-JavaScript\345\237\272\347\241\200\357\274\232\345\274\202\346\255\245\347\274\226\347\250\213/09-Promise\347\232\204\351\223\276\345\274\217\350\260\203\347\224\250.md" @@ -126,7 +126,7 @@ function requestData3(params_3) { }); } -// 【业务层】Promise 调接口的嵌套写法 +// 【业务层】Promise 调接口的嵌套写法。温馨提示:这段代码在接下来的学习中,会被改进无数次。 // 发送第一次网络请求 requestData1(params_1).then(res1 => { console.log('第一个接口请求成功:' + JSON.stringify(res1)); @@ -173,7 +173,7 @@ requestData1(params_1).then(res1 => { 这段代码很经典,你一定要多看几遍,多默写几遍,倒背如流也不过分。如果你平时的异步编程代码能写到这个水平,说明你对 Promise 已经入门了,因为绝大多数人都是用的这个写法。 -其实还有更高级、更有水平的写法,那就是用生成器、用 async ... await 来写Promise的链式调用。你把它掌握了,编程水平才能更上一层楼。我们稍后会讲。 +其实还有更高级、更有水平的写法,那就是用生成器、用 async ... await 来写Promise的链式调用,也就是改进上面的十几行代码。你把它掌握了,编程水平才能更上一层楼。我们稍后会讲。 ## Promise 链式调用:封装 Node.js 的回调方法 @@ -224,9 +224,83 @@ read(A) ## 用 async ... await 封装链式调用 -前面讲的内容是用 then().then().then() 这种 +前面讲的 Promise 链式调用是用 `then().then().then()` 这种写法。其实我们还可以用更高级的写法,也就是用生成器、用 async ... await 改写那段代码。改进之后,代码写起来非常简洁。 + +在学习这段内容之前,你需要先去《JavaScript进阶/迭代器和生成器》那篇文章里去学习迭代器、生成器相关的知识。生成器是一种特殊的迭代器,async ... await 是生成器的语法糖。 + +### 用生成器封装链式调用 + +代码举例: + +```js +// 封装 Promise 链式请求 +function getData(params_1) { + // 【关键代码】 + const res1 = yield requestData1(params_1); + const res2 = yield requestData2(res1); + const res3 = yield requestData3(res2); +} + +// 调用 Promise 链式请求 +const generator = getData(params_1); + +generator.next().value.then(res1 => { + generator.next(res1).value.then(res2 => { + generator.next(res2).value.then(res3 => { + generator.next(res3); + }) + }) +}) +``` + +生成器在执行时,是分阶段执行的,每次遇到 next()方法后就会执行一个阶段,遇到 yield 就会结束当前阶段的执行并暂停。 上方代码中,yield 后面的内容是当前阶段产生的 Promise 对象;yield 前面的内容是要传递给下一个阶段的参数。 + +### 用 async ... await 封装链式调用【重要】 + +上面的生成器代码有些晦涩难懂,实际开发中,通常不会这么写。我们更喜欢用 async ... await 语法封装 Promise 的链式调用。async ... await 是属于生成器的语法糖,写起来更简洁直观、更容易理解。 + +代码举例: + +```js +// 封装:用 async ... await 调用 Promise 链式请求 +async function getData() { + const res1 = await requestData1(params_1); + const res2 = await requestData2(res1); + const res3 = await requestData3(res2); +} + +getData(); +``` + +代码解释: + +上面的代码非常简洁。实际开发中也经常用到,非常实用。requestData1()、requestData2()、requestData3() 这三个函数都是一个Promise对象,其内部封装的代码写法已经在前面「Promise 的嵌套写法」这一小段中讲过了。 + + + + + + + + + + + + + + + + + + + + + + + + + -### diff --git "a/07-JavaScript\350\277\233\351\230\266/03-\350\277\255\344\273\243\345\231\250\345\222\214\347\224\237\346\210\220\345\231\250.md" "b/07-JavaScript\350\277\233\351\230\266/03-\350\277\255\344\273\243\345\231\250\345\222\214\347\224\237\346\210\220\345\231\250.md" index eed58ac0..94533c0d 100644 --- "a/07-JavaScript\350\277\233\351\230\266/03-\350\277\255\344\273\243\345\231\250\345\222\214\347\224\237\346\210\220\345\231\250.md" +++ "b/07-JavaScript\350\277\233\351\230\266/03-\350\277\255\344\273\243\345\231\250\345\222\214\347\224\237\346\210\220\345\231\250.md" @@ -709,7 +709,7 @@ console.log(generator.next('next3')); // 指定第三阶段 {value: undefined, done: true} ``` -在理解上方代码时需要注意的是,将 next2 这个属性值赋值给 res2,这个操作的执行时机是在**第二阶段的最开始**做的,不是在第一阶段的末尾做的。并且,这个属性值是通过第一阶段的 yield 返回值接收的。 +第一次学习时,这段代码可能比较难理解。在理解时需要注意的是,将 next2 这个属性值赋值给 res2,这个操作的执行时机是在**第二阶段的最开始**做的,不是在第一阶段的末尾做的。并且,这个属性值是通过第一阶段的 yield 返回值接收的。 ### 如何中途结束生成器的执行 @@ -872,7 +872,7 @@ console.log(valueGenerator.next()); yield* 某个可迭代对象 ``` -`yield*` 是 yield 的一种语法糖,也就是一种简写形式。它会依次迭代一个**可迭对对象**,每次迭代一个值,并产生一个**新的可迭代对象**。 +`yield*` 是 yield 的一种语法糖,也就是一种简写形式。它会依次迭代一个**可迭对对象**,每次迭代一个值,并且会产生一个**新的可迭代对象**。 我们在前面讲过可迭代对象的应用场景,简单提到过 `yield*`,接下来讲讲它具体如何使用的。