-
promise基础原理到难点分析
-
常见的Promise的方法解读
-
扩展async和await深入分析
-
逐步分析Promise底层逻辑代码
一、Promise基础
1.什么是promise
为了解决回调地狱:
//2.设置点击事件
btn.onclick = function() {
//3.创建ajax实例化对象
let xhr = new XMLHttpRequest();
//console.log('ajax实例化对象刚刚被创建出来:',xhr.readState)
//4.打开请求
xhr.open('get', 'http://iwewiki.com');
//console.log('ajax已经打开了请求',xhr.readState)
//5.发送请求(send方法中发送的是请求体数据,只不过get请求是没有请求体的,而post请求有请求体)
xhr.send()
//6.客户端接收服务端中响应回来的结果数据
xhr.onreadystatechange = function() {
// 2:已经完成了请求的发送
// 3:响应结果途中还没有完全相应结果完毕...ing
//4:已经完成了响应完毕结果了
//console.log('0',xhr.readState)
//7.判断
if (xhr.readyState === 4) {
//status:请求的状态码200-299之间
if (xhr.status >= 200 && xhr.status < 300) {
//8.获取请求数据(JSON字符串=>json对象)
console.log(JSON.parse(xhr.responseText))
}
}
}
}
2.回调地狱
promise构造函数
then方法的返回值的Promise实例化对象的状态取决于回调函数中的内容
- 如果返回为非Promise实例化对象,则得到一个是成功的Promise。
- 如果返回的是promise实例化对象,则Promise实例化对象的状态和结构值将直接影响result常量的状态和结果值。
- 如果为抛出异常,则新的Promise实例化对象(result)为失败的Promise
3.链式调用.then
对数据库进行操作:
封装一个函数来读取文件:
4.Promise.all()
Promise下的all方法作用主要是针对于多个Promise的异步任务的处理
需要接收一个数组类型的参数
返回值:Promise对象,状态也是由数组中的每一个Promise对象的状态来决定的
当所有的Promise对象的状态都是成功的,最终的结果就是成功的Promise,结果值是由每一个Promise的结果值组成的数组。
当所有的Promise对象的状态但凡有一个是失败的,最终也是失败的Promise,结果值就是失败的这个Promise的结果值
5.Promise.allSettled()
allSettled方法用来确定一组异步地操作是否都结束了(不管是成功还是失败),其中包含了fulfilled和rejected两种情况
<script>
function ajax(url) {
return new Promise((resolve, reject) => {
let xhr = new XMLHttpRequest()
xhr.open('get', url, true)
xhr.send()
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
resolve(xhr.responseText)
} else {
reject(xhr.responseText)
}
}
}
})
}
Promise.allSettled([ajax('地址1'), ajax('地址2')]).then(value => {
let errorList = value.filter(item => item.status === 'rejected')
console.log(errorList)
}).catch(reason => {
console.log(reason)
})
</script>
6.Promise.any()
有一个成功就是成功
Promise下的any方法,只要参数中有一个Promise实例化对象的状态为fulfilled,则整体结果就会为fulfilled。
如果所有Promise实力都是rejected,那么结果就是rejected
<script>
let p1 = new Promise((resolve, reject) => {
resolve('ok');
})
let p2 = new Promise((resolve, reject) => {
resolve('okk')
})
let result = Promise.any([p1, p2])
console.log(result)
</script>
7.Promise.race()
Promise.race方法是需要传递一个参数,参数为数组,数组中的内容表示的是Promise实例化对象。
如果有最想到达状态的(pending来更改成fulfilled或者是rejected),不管是成功状态还是失败的状态,都将以这个对象的状态和结果值为准。
8.Promise.reject()
Promise.reject()方法将始终返回一个为失败的Promise对象,无论参数是否为Promise还是其他,最终都将返回失败的Promise
9.Promise.resolve()
Promise下的resolve方法作用:将一个普通的值转换成Promise类型的数据.
分两种情况:
1.当resolve方法参数为非Promise对象,则返回的结果为成功的Promise对象
2.当resolve方法参数为Promise对象,则参数对象的状态和结果将直接影响最终resolve方法的返回值的那个对象的状态和结果
10.catch
①then方法中是可以传入两个参数,当然也可以不传递,也可以只传递成功的回调函数
②也可以单独来使用catch来专门指定失败的回调函数
catch方法也有返回值,和then方法的返回值类似
catch方法也返回一个Promise实例化对象
情况1:如果失败回调函数中没有返回值,则得到一个成功的promise实例化对象,结构为undefined
情况2:如果失败回调函数中有返回值,但是这个返回值不是promise实例的情况下,则得到一个成功的promise实例化对象,结构为返回值数据
情况3:如果失败回电函数中有返回值,但是这个返回值是promise实例的情况下,则新的promise对象的状态和结果值完全取决于返回的Promise对象的状态以及结果值
当然也可以和then方法结合使用
异常(错误)穿透
当如果有多个需要执行的成功的回调,可以不每一次都写失败回调,可以一次性统一使用最后一次catch
当Promise实例化对象的状态为rejected,则会一直向下穿透到catch方法
11.finally
finally是ES9中新增的特性,表示无论Promise对象变成了fulfilled还是rejected状态,最终都回执行finally方法的回调函数参数是不接受参数的。
12.终止promise链条
终止Promise链条主要就是为了返回 一个pending状态的Promise实例化对象。
13.async/await
使用async结合await的终极目标:就是同步的代码来完成异步的功能
1.async函数结合await表达式
1.1async函数中不一定要完全结合await
1.2有await的函数一定是async函数
2.await相当于then,可以直接拿到成功的Promise实例化对象的结果值
3.await一定要写在async函数之中,但是async函数之中可以没有await
4.如果await表达式后面是Promise实例化对象,则await返回的是Promise的成功的结果值
5.如果await表达式后面的其他值,则会直接将这个值作为await的返回值
try....catch可以继续执行,并可以正常获取值
14.宏队列和微队列
JS中用来存储待执行回调函数的队列中包含了另个特定的队列
宏队列:用来保存执行的宏任务(回调),比如:定时器、DOM事件操作、ajax
微队列:用来保存执行的微任务(回调),比如:promise
JS执行的时候会区分两个队列
--首先JS引擎会必须先将所有的同步代码都执行完
---每次准备取出第一个宏任务的执行之前,都需要将所有的微任务一个一个取出来执行
---顺序为 同--微--宏
二、手写Promise源码
Promise是一个构造函数,作用就是为了实例化对象。
语法:let 变量=new 构造函数名称();在堆内存中开辟一块空间,分配其大小以及设置其地址值0x100。
堆内存:主要存储的是引用数据类型的数据(数组、对象、函数)
栈内存:主要存储的是基本数据类型以及引用数据类型的地址值。
(一个函数如果作为另外一个方法的实际参数那么这么函数一定是回调函数)