update: promise

This commit is contained in:
qianguyihao 2021-05-17 17:59:58 +08:00
parent 4b2ef2d764
commit b34943e616
2 changed files with 68 additions and 44 deletions

View File

@ -1,5 +1,3 @@
## 为什么需要 Promise ## 为什么需要 Promise
我们在上一篇文章单线程和异步中讲过Javascript 单线程语早期我们解决异步场景时部分情况都是通过回调函数来进 我们在上一篇文章单线程和异步中讲过Javascript 单线程语早期我们解决异步场景时部分情况都是通过回调函数来进
@ -8,7 +6,7 @@
### 回调的定义 ### 回调的定义
把函数A传给另一个函数B调用那么函数A就是回调函数 把函数 A 传给另一个函数 B 调用那么函数 A 就是回调函数
例如在浏览器中发送 ajax 请求就是常个异步场景发送请求后需要等待一段时间等服务端响应之后我们才能拿到结果如果我们希望在异步结束之后执某个操作就只能通过**回调函数**这样的式进操作 例如在浏览器中发送 ajax 请求就是常个异步场景发送请求后需要等待一段时间等服务端响应之后我们才能拿到结果如果我们希望在异步结束之后执某个操作就只能通过**回调函数**这样的式进操作
@ -26,22 +24,31 @@ dynamicFunc(function () {
例如上这个例dynamicFunc 就是个异步函数 setTimeout 会在 1s 之后调 callback 函数按照上的调最终 1s 之后会打印 qian gu 这个结果 例如上这个例dynamicFunc 就是个异步函数 setTimeout 会在 1s 之后调 callback 函数按照上的调最终 1s 之后会打印 qian gu 这个结果
为了能使回调函数以更优雅的式进 ES6 语法中新增了个名为 Promise 的新规范 为了能使回调函数以更优雅的式进 ES6 语法中新增了个名为 Promise 的新规范
### 回调的缺点 ### 回调的缺点
回调的写法比较直观不需要 return层层嵌套即可但也存在两个问题 回调的写法比较直观不需要 return层层嵌套即可但也存在两个问题
- 1如果嵌套过深则会出现**回调地狱**的问题 - 1如果嵌套过深则会出现**回调地狱**的问题
- 2不同的函数回调的参数在写法上可能不一致导致不规范且需要**单独记忆** - 2不同的函数回调的参数在写法上可能不一致导致不规范且需要**单独记忆**
我们来具体看看这两个问题 我们来具体看看这两个问题
**1回调地狱的问题** **1回调地狱的问题**
如果后续还有内容需要在异步函数结束时输出就需要多个异步函数进嵌套常不利于后续的维护而且会导致**回调地狱**的问题 如果多个异步函数存在依赖关系比如需要等第一个异步函数执行完成后才能执行第二个异步函数等第二个异步函数执行完毕后才能执行第三个异步函数就需要多个异步函数进层层嵌套常不利于后续的维护而且会导致**回调地狱**的问题
关于回调地狱我们来举一个形象的例子
> 假设买菜做饭洗碗倒厨余垃圾都是异步的
> 但真实的场景中实际的操作流程是买菜成功之后才能开始做饭做饭成功后才能开始洗碗洗碗完成后 再倒厨余垃圾这里的一系列动作就涉及到了多层嵌套调用也就是回调地狱
关于回调地狱我们来看看两段代码
定时器的代码举例
```js ```js
setTimeout(function () { setTimeout(function () {
@ -55,13 +62,20 @@ setTimeout(function () {
}, 1000); }, 1000);
``` ```
关于回调地狱我们来举一个形象的例子 ajax 请求的代码举例
假设买菜做饭洗碗倒厨余垃圾都是异步的 ```js
// 伪代码
但真实的场景中实际的操作流程是买菜成功之后才能开始做饭做饭成功后才能开始洗碗洗碗完成后 再倒厨余垃圾这里的一系列动作就涉及到了多层嵌套调用也就是回调地狱 ajax('a.json', (res1) => {
console.log(res1);
ES5 当进行多层嵌套回调时会导致代码层次过多很难进行后续维护和二次开发而且会导致**回调地狱**的问题ES6 中的 Promise 就可以解决这两个问题 ajax('b.json', (res2) => {
console.log(res2);
ajax('c.json', (res3) => {
console.log(res3);
});
});
});
```
**2回调的写法不一致问题** **2回调的写法不一致问题**
@ -73,8 +87,7 @@ readFile('d:\\readme.text', function (error, data) {
} else { } else {
console.log('文件读取成功'); console.log('文件读取成功');
} }
}) });
// jQuery的 ajax 写法中,成功回调和失败回调,是通过两个回调函数来区分 // jQuery的 ajax 写法中,成功回调和失败回调,是通过两个回调函数来区分
$.ajax({ $.ajax({
@ -84,15 +97,17 @@ $.ajax({
}, },
error: function (err) { error: function (err) {
console.log('文件读取失败'); console.log('文件读取失败');
},
} });
})
``` ```
我们可以看到上面的代码中成功回调和失败回调写法不统一需要单独记忆容易出错 我们可以看到上面的代码中成功回调和失败回调写法不统一需要单独记忆容易出错
**小结**
ES5 当进行多层嵌套回调时会导致代码层次过多很难进行后续维护和二次开发而且会导致**回调地狱**的问题ES6 中的 Promise 就可以解决这两个问题
当然 Promise 的更强大功能不止于此我们来一探究竟
### Promise 的介绍和优点 ### Promise 的介绍和优点
ES6 中的 Promise 是异步编程的一种方案从语法上讲Promise 是一个对象它可以获取异步操作的消息 ES6 中的 Promise 是异步编程的一种方案从语法上讲Promise 是一个对象它可以获取异步操作的消息
@ -108,15 +123,21 @@ Promise 的伪代码结构,大概是这样的:
```js ```js
// 伪代码1 // 伪代码1
myPromise() myPromise()
.then(function () { }, function () { }) .then(
.then(function () { }, function () { }) function () {},
.then(function () { }, function () { }) function () {}
)
.then(
function () {},
function () {}
)
.then(
function () {},
function () {}
);
// 伪代码2 // 伪代码2
是时候展现真正的厨艺了() 是时候展现真正的厨艺了().然后(买菜).然后(做饭).然后(洗碗);
.然后(买菜)
.然后(做饭)
.然后(洗碗)
``` ```
上面的伪代码可以看出即便在业务逻辑上是层层嵌套但是代码写法上却十分优雅也没有过多的嵌套 上面的伪代码可以看出即便在业务逻辑上是层层嵌套但是代码写法上却十分优雅也没有过多的嵌套
@ -131,6 +152,8 @@ myPromise()
3通过 promise.then() 处理返回结果这里的 `promise` 指的是 Promise 实例 3通过 promise.then() 处理返回结果这里的 `promise` 指的是 Promise 实例
Promise的精髓在于**对异步操作的状态管理**
接下来我们来具体看看 promise 的代码是怎么写的 接下来我们来具体看看 promise 的代码是怎么写的
### Promise 处理异步任务的过程 ### Promise 处理异步任务的过程
@ -259,9 +282,7 @@ try-catch 主要用于捕获异常,注意,这里的异常是指**同步**函
原因是当异步函数抛出异常时对于宏任务而言执行函数时已经将该函数推入栈此时并不在 try-catch 所在的栈所以 try-catch 并不能捕获到错误对于微任务而言比如 promisepromise 的构造函数的异常只能被自带的 reject 也就是.catch 函数捕获到 原因是当异步函数抛出异常时对于宏任务而言执行函数时已经将该函数推入栈此时并不在 try-catch 所在的栈所以 try-catch 并不能捕获到错误对于微任务而言比如 promisepromise 的构造函数的异常只能被自带的 reject 也就是.catch 函数捕获到
2写法 1 `promiseA().then().catch()``promiseA().catch().then()`区别在于前者可以捕获到 `then` 里面的异常后者不可以
2写法1中`promiseA().then().catch()``promiseA().catch().then()`区别在于前者可以捕获到 `then` 里面的异常后者不可以
### 小结 ### 小结
@ -273,16 +294,15 @@ try-catch 主要用于捕获异常,注意,这里的异常是指**同步**函
4失败的 promise后续可以通过 promise 自带的 .catch 法或是 .then 法的第个参数进捕获 4失败的 promise后续可以通过 promise 自带的 .catch 法或是 .then 法的第个参数进捕获
## Promise 规范 ## Promise 规范
### Promise 规范解读 ### Promise 规范解读
Promise 个拥有 then 法的对象或函数任何符合 promise 规范的对象或函数都可以成为 Promise Promise 个拥有 then 法的对象或函数任何符合 promise 规范的对象或函数都可以成为 Promise
关于promise 规范的详细解读可以看下面这个链接 关于 promise 规范的详细解读可以看下面这个链接
- Promises/A+ 规范<https://promisesaplus.com/> - Promises/A+ 规范<https://promisesaplus.com/>
## promise 对象的 3 个状态 ## promise 对象的 3 个状态
@ -483,8 +503,7 @@ request1()
## 总结 ## 总结
了解这些内容之后 你已经对 Promise 有了基本了解下一篇文章我们来讲一讲 Promise 在实战开发的常见用法
了解这些内容之后 你已经对 Promise 有了基本了解下一篇文章我们来讲一讲 Promise在实战开发的常见用法
## 参考链接 ## 参考链接

View File

@ -2,7 +2,7 @@
## 同步和异步 ## 同步和异步
### 同步和异步的概念 ### 同步和异步的简单理解
- 同步必须等待前面的任务完成才能继续后面的任务 - 同步必须等待前面的任务完成才能继续后面的任务
@ -19,12 +19,15 @@
我们在访问一个普通的网站时当浏览器加载完`HTML、CSS、JS`以后网站的内容就固定了如果想让网站内容发生更改就必须**刷新**页面才能够看到更新的内容 我们在访问一个普通的网站时当浏览器加载完`HTML、CSS、JS`以后网站的内容就固定了如果想让网站内容发生更改就必须**刷新**页面才能够看到更新的内容
可如果用到**异步更新**情况就大为改观了比如我们在访问新浪微博时看到一大半了点击底部的**加载更多**会自动帮我们加载更多的微博同时页面并没有刷新 可如果用到**异步更新**情况就大为改观了比如我们在访问新浪微博时看到一大半了点击底部的**加载更多**会自动帮我们加载更多的微博同时页面并不会整体刷新
试想一下如果没有异步刷新的话每次点击加载更多网页都要刷新体验就太不好 试想一下如果没有异步刷新的话每次点击加载更多网页都要重新刷新体验就太糟糕
web前端里的异步更新就要用到 Ajax web前端里的异步更新就要用到 Ajax
关于同步和异步的更详细介绍可以参考本项目的另外一篇文章JavaScript基础ES6语法/单线程和异步
## Ajax ## Ajax
@ -49,9 +52,9 @@ AjaxAsynchronous Javascript And XML异步 JavaScript 和 XML。它并
发送 Ajax 请求的五个步骤 发送 Ajax 请求的五个步骤
1创建异步对象 XMLHttpRequest 对象 1创建异步对象 XMLHttpRequest 对象
2使用open方法设置请求的参数open(method, url, async)参数解释请求的方法请求的url是否异步 2使用open方法设置请求的参数`open(method, url, async)`参数解释请求的方法请求的url是否异步
3发送请求 3发送请求
@ -59,7 +62,7 @@ AjaxAsynchronous Javascript And XML异步 JavaScript 和 XML。它并
如果要在数据完整请求回来的时候才调用我们需要手动写一些判断的逻辑 如果要在数据完整请求回来的时候才调用我们需要手动写一些判断的逻辑
5获取返回的数据 5服务端响应获取返回的数据
### Ajax 请求get 请求举例 ### Ajax 请求get 请求举例
@ -644,11 +647,13 @@ echo $text;
## 我的公众号 ## 创作不易赞赏作者
想学习<font color=#0000ff>**代码之外的技能**</font>****id`qianguyihao` 如果你觉得本教程对你有帮助或者你想催更不妨赞赏一下
扫一扫你将发现另一个全新的世界而这将是一场美丽的意外 你的赞赏和认可是我最大的动力
![](http://img.smyhvae.com/20210510_2100.jpg)
![](http://img.smyhvae.com/2016040102.jpg)