目录
一、介绍和基本使用
- 是ES6的新特性;
- 是异步编程的解决方案
- 避免ajax异步请求导致回调函数嵌套太深,陷入回调地狱
基本使用
这里使用setTimeout作为模拟网络请求:
模拟回调地狱
//异步操作
setTimeout(function () {
console.log(123)
console.log(123)
console.log(123)
setTimeout(()=>{
console.log(456)
console.log(456)
console.log(456)
setTimeout(()=>{
console.log(789)
console.log(789)
console.log(789)
},1000)
},1000)
},1000)
使用Promise
<script>
//异步操作
new Promise((resolve, reject) => {
//第一次网络请求的代码
setTimeout(() => {
resolve(123)
}, 1000)
}).then((a)=>{
//第一次拿到结果的处理代码
console.log(a)
console.log(a)
console.log(a)
return new Promise((resolve, reject)=>{
//第二次网络请求的代码
setTimeout(()=>{
resolve(456)
},1000)
}).then((b)=>{
//第二次结果处理的代码
console.log(b)
console.log(b)
console.log(b)
return new Promise((resolve,reject)=>{
//第三次网络请求的代码
setTimeout(()=>{
resolve(789)
},1000)
}).then((data)=>{
//第三次处理的代码
console.log(data)
console.log(data)
console.log(data)
})
})
})
</script>
网络请求都在Promise对象中,每次处理的回调函数都在Promise.then方法中
一般情况下,是有异步操作时,使用Promise对这个异步操作进行封装
new ->构造函数(1、保存一些状态信息,2、执行传入的函数)
在执行传入的回调函数时,会传入两个参数,resolve,reject,本身又是函数;
new Promise((resolve,reject)=>{
执行网络请求
resolve(参数x)//代替成功时处理结果的代码
或者reject(参数y)//代替失败时处理结果的代码
}).then((参数x)=>{
处理成功的操作
}).catch((参数y)=>{
处理失败的操作
})
成功处理调用resolve,失败调用reject
二、Promise的三种状态
异步操作之后会有三种状态:
- pending:等待状态,正在进行异步操作(网络请求),还没有返回结果;
- fulfill:满足状态,当我们主动回调了resolve方法时,就处于该状态,并且这个时候会回调then();
- reject:拒绝状态,当我们主动回调了reject时,就会处于改状态,并且同时回调catch();
三、Promise的链式调用
第一种链式调用
见上一的回调地狱的Promise的处理
第二种链式调用
原:
<script>
new Promise(resolve => {
setTimeout(() => {
resolve('aaa')
}, 1000)
}).then(res => {
//1、处理返回结果的代码
console.log(res, '第一层的十行处理结果');
//2、
return new Promise(resolve => {
resolve(res + '111')
}).then(res => {
console.log(res, '第二层的十行处理结果')
return new Promise(resolve => {
resolve(res+'333')
}).then(res=>{
console.log(res,'第三层的十行处理结果')
})
})
})
</script>
简化:
new Promise(resolve => {
setTimeout(() => {
resolve('aaa')
}, 1000)
}).then(res => {
console.log(res, '第一层的十行处理结果');
return Promise.resolve(res + '111')
}).then(res => {
console.log(res, '第二层的十行处理结果')
return Promise.resolve(res + '333')
}).then(res => {
console.log(res, '第三层的十行处理结果')
})
继续简化
new Promise(resolve => {
setTimeout(() => {
resolve('aaa')
}, 1000)
}).then(res => {
console.log(res, '第一层的十行处理结果');
return res + '111'
}).then(res => {
console.log(res, '第二层的十行处理结果')
return res + '333'
}).then(res => {
console.log(res, '第三层的十行处理结果')
})
四、Promise的all方法使用
待优化的代码
<script> let isResult1 = false let isResult2 = false //请求一: $ajax({ url: '', success: function () { isResult1 = true handlerResult() }, error: function () { } }) 请求二 $ajax({ url: '', success: function () { isResult2 = true handlerResult() }, error: function () { } }) //需求本身依赖两个请求,只有两个请求都拿到了才可以进行操作,但不确定先拿到那个结果 function handlerResult() { if (isResult1 && isResult2) { //这个时候两个请求都拿到了,可以进行处理了 } } </script>
使用Promise优化后的代码
<script>
Promise.all([
new Promise(((resolve, reject) => {
$ajax({
url: 'url1',
success: function (data) {
resolve(data)
},
error: function (error) {
reject(error)
}
})
})),
new Promise(((resolve, reject) => {
$ajax({
url: 'url2',
success: function (data) {
resolve(data)
},
error: function (error) {
reject(error)
}
})
}))
]).then(results => {
results[0]//第一个返回的结果
results[1]//第二个返回的结果
}).catch(errors=>{
errors[0]
errors[1]
})
</script>
Promise.all()的参数是一个可迭代对象,例如数组