Promise的使用
1.promise是啥
-
抽象理解
- promise是JS中进行异步编程的新的解决方案,代替以往的旧的方案(纯回调)
-
具体理解
- Promise是一个构造函数
- 是用来封装异步操作,并来获取结果的一个函数
2.promise状态
-
pedding => resolved
-
pedding => rejected
Promise 的状态只有这三种,pedding是开始,resolve是成功,reject是失败
- 无论成功与否,都会有一个结果数据
- 成功的数据成为 value,执行reject,失败的数据称为 reason,执行reject
2.执行流程
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v33Jj41Y-1591100926186)(Promise.assets/image-20200430204806673.png)]
3.基本使用
// 1. 创建promise对象
const promise = new Promise((resolve, reject) => {
// 执行器函数,执行异步任务(该执行器函数是同步回调函数)
// 1. 执行成功, 调用resolve
// 2. 执行失败, 调用reject
let time = +new Date()
if (time % 2 === 0) {
resolve('时间戳为2的整数, 执行resolve, time=' + time)
} else {
reject('时间戳错误, 执行reject, time=' + time)
}
})
promise.then(
value => {
// onResolved函数, 本质就是传入promise的回调函数resolve
console.log(value)
},
reason => {
// onRejected函数, 本质就是传入promise的回调函数reject
console.log(reason)
}
)
-
注意:传入promise中的执行器函数是同步回调函数,优先执行,不会传入任务队列
console.log(1) const p = new Promise((resolve, reject) => { console.log(2) }) console.log(3) // 结果: // 1 2 3
4.思考:为什么用promise
Promise的优点(优点):
-
Promise指定回调函数的方式更加灵活
纯回调方式:回调函数必须在异步任务开始前指定
Promise方式:在异步任务启动前/启动后/异步任务完成,再来指定对应处理的回调函数
/** * 纯回调方式 */ function scuuessCallback() { console.log('异步任务成功') } function faikureCallback() { console.log('异步任务成功') } getJsonData(option, scuuessCallback, faikureCallback) { // Do async tasks if(data) { scuuessCallback() } else { faikureCallback() } } /** * Promise方式 */ const p = new Promise((resolve, reject) => { // Do async tasks // Promise内部的执行器函数是同步回调函数,在Promise创建完成时边开始异步任务 if(data) { resolve() } else { reject() } }) p.then( // 在异步任务完成后再指定 成功|失败 回调函数 response => { console.log('异步任务成功') }, reason => { console.log('异步任务成功') } )
-
Promise支持链式调用,可以解决回调地狱问题
回调地狱:
- 回调函数嵌套调用,外部回调函数的结果会影响内部回调函数,非常不便于阅读,
- 不便于异常的处理
- 剥夺了回调函数return返回值
Promise:
- 解决回调地狱,大大提升可读性
- 出现异常能被捕获
- 能进行return返回值
终极解决方案:async / await
/** * 回调地狱:在一次ajax的success回调函数中多次嵌套请求 * 1. 回调函数嵌套调用,外部回调函数的结果会影响内部回调函数,非常不便于阅读, * 2. 不便于**异常**的处理 * 3. 剥夺了回调函数return返回值 */ function ajax(option, callback) { // do async something } function getJsonData() { ajax({ url: 'https://aaa.bbb.ccc', method: 'GET', success: function (res) { let firstId = res.id // 获得一次请求数据的id let secondId, thirdId // 定义接受第二次第三次请求数据的变量 if (res) { ajax({ // 在success回调函数中进行第二次请求 url: 'https://ddd.eee.fff', method: 'POST', data: { id: firstId }, success: function (res) { secondId = res.id if (res) { ajax( // 在success回调函数中进行第二次请求 { url: 'https://ddd.eee.fff', method: 'POST', data: { id: firstId }, success: function (res) { thirdId = res.id if(thirdId === firstId) { console.log('通过') } } } ) } } }) } } }) } /** * Promise解决回调地狱 * 1. 解决回调地狱,大大提升可读性 * 2. 出现异常能被捕获 * 3. 能进行return返回值 */ new Promise((resolve, reject) => { ajax({ url: 'http://aaa.bbb.ccc', success: function (res) { if (res) { resolve(res) } } }) }).then( res => { console.log('第一次请求成功') return new Promise((resolve, reject) => { ajax({ url: 'http://bbb.ccc.ddd', success: function (res) { if (res) { resolve(res) } } }) }) } ).then( res => { console.log('第二次请求成功') return new Promise((resolve, reject) => { ajax({ url: 'http://bbb.ccc.ddd', success: function (res) { if (res) { resolve(res) } } }) }) } ).catch( err => { // 所有错误都会在这里被捕捉 } )