一、什么是Promise
目录
六、Promise的all方法调用(某一个需求需要发送两次请求)
一、什么是Promise
1.Promise到底是做什么的呢?
Promise是异步编程的种解决方案
那什么时候我们会来处理异步事件呢?
一种很常见的场景应该就是网络请求了。
我们封装一个网络请求的函数,因为不能立即拿到结果,所以不能像简单的3+4=7—样将结果返回。
所以往往我们会传入另外—个函数,在数据请求成功时,将数据通过传入的函数回调出去。
如果只是一个简单的网络请求,那么这种方案不会给我们带来很大的麻烦
但是,当网络请求非常复杂时,就会出现回调地狱。
2.什么是回调地狱。
我们来考虑下面的场景(有夸张的成分):
我们需要通过一个urI从服务器加载一个数据data,data1中包含了下一个请求的url2
我们需要通过data1取出url2,从服务器加载数据data2,data2中包含了下ー个请求的url3
我们需要通过data2取出urI3,从服务器加载数据data3,data3中包含了下ー个请求的ur4
发送网络请求ur4,获取最终的数据data4
上面的代有什么问题吗?
正常情况下,不会有什么问题,可以正常运行并目获取我们想要的结果
但是,这样的代看而且不容易维护
我们更加期望的是一种更加优雅的方式来进行这种异步操作。
如何做呢?就是使用 Promise。——Promise可以以一种非常优雅的方式来解决这个问题。
二、Promise基本语法
1.这里,我们用个定时器来模拟异步事件:
假设下面的data是从网络上1秒后请求的数据
console. log就是我们的处理方式。
这是我们过去的处理方式,我们将它换成 Promise代码
这个例子会让我们感觉脱裤放屁,多此一挙
首先,下面的 Promise代码明显比上面的代码看起来还要复杂
其次,下面的 Promise代吗中包含的 resolve、 reject、then、catch都是些什么东西?
我们先不管第一个复杂度的问题,因为这样的一个屁大点的程序根本看不出来 Promise真正的作用.
2.上代码
<script>
// new Promise时有两个参数,resolve, reject,这两个参数同时又是函数
new Promise((resolve, reject) => {
// 1.第一次网络请求
setTimeout(function() {
// 一秒后会执行
console.log('time out')
resolve('Hello world') // 调用resolve之后,会调用下面的then
//失败时调用reject
// reject('Error data')
}, 1000)
}).then(data => {
// 2.第一次拿到结果
console.log(data)
return new Promise((resolve, reject) => {
// 3.第二次网络请求
setTimeout(function() {
// 一秒后会执行
console.log('time out2')
resolve('Hello world2') // 调用resolve之后,会调用下面的then
reject('Error data2')
}, 1000)
}).then(data => {
// 4.第二次拿到结果处理
console.log(data)
}).catch(error => {
console.log(error)
})
//如果还有处理,可以继续return new Promise
}).catch(error => {
console.log(error)
})
// new Promise是异步处理,不影响后面的逻辑
console.log('最后的')
</script>
3.另外一种写法
<script>
// new Promise时有两个参数,resolve, reject,这两个参数同时又是函数
new Promise((resolve, reject) => {
// 1.第一次网络请求
setTimeout(function() {
// 一秒后会执行
console.log('time out')
resolve('Hello world') // 调用resolve之后,会调用下面的then
reject('Error data')
}, 1000)
}).then(data => {
// 2.第一次拿到结果
// 只写一个then,可以传入两个函数,一个resolve执行,一个reject执行
console.log(data)
}, error => {
console.log(error)
})
</script>
三、什么情况下需要使用Promise
在进行 异步请求时,使用Promise对这个异步操作进行封装。
在处理完结果之后,使用resolve方法就会调用promise后面的then方法;报错之后,reject会调用catch方法。
在执行传入的回调函数时,会传入两个参数,resolve、reject,本身又是函数
四、Promise三种状态
首先,当我们开发中有异步操作时,就可以给异步操作包装一个Promise。异步操作之后会有三种状态:
pending:等待状态,比如正在进行网络请求,或者定时器没有到时间。
fulfill:满足状态,当我们主动回调了resolve时,就处于该状态,并且会回调then()
reject:拒绝状态,当我们主动回调了reject时,就处于该状态,并且会回调catch()
五、Promise链式调用
1.链式调用
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('aaa')
}, 1000)
}).then(res => {
//1.自己处理10行代码
console.log(res, '第一层的10行处理代码')
// 2.对结果进行第一次处理,可以只用resolve
return new Promise((resolve) => {
resolve(res + '111')
})
}).then(res => {
console.log(res, '第二层的10行处理代码')
return new Promise((resolve) => {
resolve(res + '222')
})
}).then(res => {
console.log(res, '第三层的10行处理代码')
})
// aaa 第一层的10行处理代码
// aaa111 第二层的10行处理代码
// aaa111222 第三层的10行处理代码
2.简化链式
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('aaa')
}, 1000)
}).then(res => {
//1.自己处理10行代码
console.log(res, '第一层的10行处理代码')
// 2.对结果进行第一次处理,可以只用resolve
return Promise.resolve(res + '111')
}).then(res => {
console.log(res, '第二层的10行处理代码')
return Promise.resolve(res + '222')
}).then(res => {
console.log(res, '第三层的10行处理代码')
})
// aaa 第一层的10行处理代码
// aaa111 第二层的10行处理代码
// aaa111222 第三层的10行处理代码
3.极度简化
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('aaa')
}, 1000)
}).then(res => {
//1.自己处理10行代码
console.log(res, '第一层的10行处理代码')
// 2.对结果进行第一次处理,可以只用resolve
return res + '111'
}).then(res => {
console.log(res, '第二层的10行处理代码')
return res + '222'
}).then(res => {
console.log(res, '第三层的10行处理代码')
})
// aaa 第一层的10行处理代码
// aaa111 第二层的10行处理代码
// aaa111222 第三层的10行处理代码
4.reject的简写
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('aaa')
}, 1000)
}).then(res => {
//1.自己处理10行代码
console.log(res, '第一层的10行处理代码')
// 2.对结果进行第一次处理,可以只用resolve
return Promise.reject(res + '111')
//throw 'errormsg' // 手动抛出异常也可以
}).then(res => {
console.log(res, '第二层的10行处理代码')
return Promise.resolve(res + '222')
}).then(res => {
console.log(res, '第三层的10行处理代码')
}).catch(err => {
console.log(err, 'err')
})
//aaa 第一层的10行处理代码
//aaa111 err
六、Promise的all方法调用(某一个需求需要发送两次请求)
Promise.all([
new Promise((resolve, reject) => {
// 1.第一次请求
setTimeout(() => {
resolve('aaa1')
}, 1000)
}),
new Promise((resolve, reject) => {
// 2.第二次请求
setTimeout(() => {
resolve('aaa2')
}, 2000)
})
]).then(results => {
// 每个数组对应每个Promise,只有所有的Promise都执行完毕之后,才会调用then方法
console.log(results[0])
console.log(results[1])
})