解释:JavaScript 中存在很多异步操作,Promise 将异步操作队列化,按照期望的顺序执行,返回符合预期的结果。可以通过链式调用多个 Promise 达到我们的目的
旧代码(没有使用Promise):此代码需要嵌套调用,写起来很难维护。
<script>
setTimeout(()=>{
console.log(1)
setTimeout(()=>{
console.log(2)
setTimeout(()=>{
console.log(3)
})
},10)
},10)
</script>
新代码(使用Promise):链式结构使用方便
<script>
new Promise((resolve)=>{
setTimeout(()=>{
console.log(1)
resolve('success')
},1000)
}).then(()=>{
setTimeout(()=>{
console.log(2)
},1000)
}).then(()=>{
setTimeout(()=>{
console.log(3)
},1000)
})
</script>
总结:上面的使用Promise打印出 1 2 3
,但其实并非按照你想的那样去执行,需要知道原理便于下面的学习,阅读JavaScript任务管理
解释:Promise无法让异步程序成为同步程序,它只是让异步程序后面紧跟一个微任务,以便于异步完成之后执行你想要的操作(被放到微任务),Promise 包含pending、fulfilled、rejected三种状态
解释:resolve(其实它是第一个参数,可以随便命名)配合的就是then****,当程序碰到resolve才会进行then操作(没有的话then根本不会被执行),then无需resolve反馈(写上还会报错),默认就是(promise 状态设置为fulfilled)(可以自己设置返回的Promise对象),代码如下
new Promise((resolve,reject)=>{
console.log(123)
resolve('fl')
}).then(()=>{
console.log(2)
})
解释:reject(其实它是第二个参数,可以随便命名)配合使用的就是catch,当程序碰到reject才会进行catch操作,代码如下
new Promise((resolve,reject)=>{
console.log(123)
reject('fl')
}).then(()=>{
console.log(2)
}).catch((a)=>{
console.log(a)
})
// 结果
123
fl
解释:无论状态是resolve 或 reject 都会执行此动作,finally 与状态无关
应用:通过其全部完成后才返回的特性,可以通过其放几个异步请求,当在加载时显示加载动画,全部加载完成后,再设置显示页面
var a = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('fl')
}, 5000)
})
var b = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('fl')
}, 1000)
})
Promise.all([a, b])
.then(results => {
console.log(results);
})
// 结果(这个会等5秒才执行(最长所需要的时间))
['fl', 'fl']
区别(同all):其不关心是否全部成功,其永远会成功返回结束(而all遇到错误会报错)
var a = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('fl')
}, 5000)
})
var b = new Promise((resolve, reject) => {
setTimeout(() => {
reject('fl')
}, 1000)
})
Promise.allSettled([a, b])
.then(results => {
console.log(results);
})
// 结果
[{…}, {…}]
// 展开后
0
:
{status: 'fulfilled', value: 'fl'}
1
:
{status: 'rejected', reason: 'fl'}
length
:
2
[[Prototype]]
:
Array(0)
区别(同all):当其中某一个Promise(最快的)返回后,其race就会结束,(其它Promise还会再执行,只是不会把值反馈到race里面)
应用:数组里面只放二个Promise(一个是异步,一个是定时器),当其获取时间过长时,提示用户。
// 假设a是异步请求
var a = new Promise((resolve, reject) => {
setTimeout(() => {
console.log(1)
resolve('fl')
}, 5000)
})
// 假设b是当a超时后反馈的定时器(超过两秒就超时)
var b = new Promise((resolve, reject) => {
setTimeout(() => {
console.log(2)
reject('fl')
}, 2000)
})
Promise.race([a, b])
.then(results => {
console.log(results);
}).catch((h)=>{
alert(h)
})
需求:先获得到用户的ID,再通过用户ID获取到用户名,再通过ID和用户名再获取用户的身份信息(需要先获取用户ID,再获取用户名,再获取用户身份信息(前后顺序不能改变))
代码实现:
<script>
var aa = 1, bb = 1, cc = 1;
function a() {
return new Promise((resolve, reject) => {
setTimeout(() => {
aa = 9;
console.log(1)
resolve('1')
}, 5000)
})
}
function b() {
return new Promise((resolve, reject) => {
setTimeout(() => {
bb = aa + 10;
console.log(bb)
resolve('2')
}, 7000)
})
}
function c() {
return new Promise((resolve, reject) => {
setTimeout(() => {
cc = bb + aa + 11;
console.log(cc)
resolve('3')
}, 5000)
})
}
a().then(() => {
return b();
}).then(() => {
return c();
}).then(() => {
console.log('ok')
})
</script>