Promise解决什么问题
异步操作的回调地狱,可以让异步操作写起来,就像写同步操作一样
php
// 异步操作的回调地狱问题
$.ajax({
type: 'GET',
url: '/a',
data:{},
success: res => {
const id = res.data;
$.ajax({
type: 'GET',
url: '/b',
data:{
id,
},
success: res => {
const username = res.data;
$.ajax({
type: 'GET',
url: '/b',
data:{
id,
},
success: res => {
const username = res.data;
}
});
}
});
}
});
php
// 使用promise后,就像写同步操作一样写异步操作
const p = new Promise((resolve, reject) => {
$.ajax({
type: 'GET',
url: '/a',
data:{},
success: res => {
resolve(res);
}
error: res => {
reject(res)
}
})
}.then(res => {
$.ajax({
type: 'GET',
url: '/b',
data:{},
success: res => {
resolve(res);
}
error: res => {
reject(res)
}
})
}).then(res => {
$.ajax({
type: 'GET',
url: '/c',
data:{},
success: res => {
resolve(res);
}
error: res => {
reject(res)
}
})
}).
kotlin
// 结合async await,可进一步消除回调的影子
const resA = await axios.get('/a');
const resB = await axios.get('/b', { id: resA.data.data });
const resC = await axios.get('/c', { username: resB.data.data });
Promise的基本使用
Promise是构造函数,用new实例化
Promise是一个构造函数,使用new进行实例化。
该构造函数入参是一个函数,函数包含两个参数:resolve/reject,均为函数,接受一个参数,即为promise的结果
javascript
const p = new Promise((resolve, reject) => {
});
Promise实例的3种状态
- 初始状态pending
- 已完成fulfilled
- 已失败rejected
Promise状态变化是一次性的,即pending=>fulfilled,或者pending=>rejected。当resolved(fulfilled/rejected)后,无法再变更为其他状态,即Promise状态不可逆。
状态变更&结果返回
- => fulfilled
调用resolve函数
- => rejected
调用reject函数或者代码报错
javascript
const p = new Promise((resolve, reject) => {
resolve('success');
// reject('failed'); // 不生效,promise状态不可逆
});
const p2 = new Promise((resolve, reject) => {
reject('failed');
});
Promise常用方法
实例方法
🌟🌟🌟then方法
入参:
- 两个函数,第一个为状态转为fulfilled时的成功回调,第二个为状态转为rejected时的失败回调(不常用)
- 成功回调和失败回调的参数为前面promise中resolve或者reject的值
返回:一个新的promise实例
javascript
const p = new Promise((resolve, reject) => {
resolve('123');
// reject('456');
}).then((val) => {}, (err) => {});
then方法的回调函数是异步操作,会在当前同步逻辑执行完之后执行(当前EventLoop的结尾,微任务)。但是注意使用Promise构造函数初始化Promise实例的入参数是同步执行的,不要搞混了。
javascript
console.log('1')
const p = new Promise((resolve, reject) => {
console.log('2');
resolve('success');
}).then((val) => {
console.log('3');
})
console.log('4');
// 输出:1,2,4,3
then方法返回的Promise实例通过return进行状态流转
javascript
const p = new Promise((resolve, reject) => {
resolve('success');
}).then((val) => {
})
const p1 = new Promise((resolve, reject) => {
resolve('success');
}).then((val) => {
return val;
})
🌟🌟 catch方法
入参:reject传递的值或者异常报错
返回:仍然返回一个新的promise
失败回调除了then的第二个参数之外,还可以调用catch方法,通常这种方法更常用。原因如下:
javascript
const p = new Promise((resolve, reject) => {
resolve('success');
}).then(val => {
// ...
// 发生异常
//
}, err => {
// ❌无法捕获异常
}).catch(val => {
// ✅能够捕获异常
});
🌟 finally方法
成功或者失败回调后,都会执行该函数,按需使用。
类方法
🌟🌟 Promise.resolve
返回一个fulfilled状态的promise实例,通常用于快速构造Promise,统一异步操作接口。以下是一个缓存优化的例子
kotlin
let cachedData;
function getData() {
if (cachedData) {
return Promise.resolve(cachedData); // 直接返回缓存
}
return fetch('url').then(data => {
cachedData = data;
return data;
});
}
或者某个同步任务耗时比较久,用来构造一个微任务,从而不阻塞主流程
javascript
Promise.resolve().then(() => {
// 复杂计算逻辑
})
🌟 Promise.reject
与Promise.resolve类似
🌟🌟 Promise.all
将多个promise实例封装成一个promise
🌟🌟 Promise.race
Promise.race的妙用。这个在我的业务代码中也用到了这个小技巧。
参考资料
阮一峰ES6教程:es6.ruanyifeng.com/#docs/promi...