Promise 是进行异步操作的构造函数。Promise 对象用于表示一个异步操作的最终完成 (或失败), 及其结果值.
Promise
参数
Promise 接收一个函数,并传入两个参数 resolve和reject ,分别表示异步操作执行成功后的回调函数和异步操作执行失败后的回调函数。
new Promise((resolve, reject) => {
// 成功||将promise的状态改为fulfilled
resolve()
// 失败||将promise的状态改为rejected
reject()
})
顾名思义是承诺,以后会发生的事情。
描述
Promise有以下几种状态:
- pending: 初始状态,既不是成功,也不是失败状态。
- fulfilled: 意味着操作成功完成。
- rejected: 意味着操作失败。
Promise 的状态一旦发生变化,就会一直保持这个状态,是不可逆的状态。
当Promise状态为fulfilled时 => 调用 .then() 方法
当Promise状态为rejected时 => 调用 .catch() 方法
方法
.then()
当状态发生变化时,会调用.then() 绑定的函数方法。
Promise.then(
success => {
// 成功 resolve
},
error => {
// 失败 reject
}
)
.catch()
当 JS执行异常报错时,会执行.catch()捕获错误信息
Promise.catch(
// 捕获错误
)
.all()
var p = Promise.all([p1(), p2(), p3()])
all()接受数组作为参数。
数组中的p1,p2,p3都是Promise的实例对象,p要变成Resolved状态需要p1,p2,p3状态都是Resolved。
如果p1,p2,p3至少有一个状态是Rejected,p就会变成Rejected状态。
即便只有一个是失败的状态,整体都会变成失败的状态
.race()
用法和 .all()方法一样,也是接收数组作为参数。
只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。
那个率先改变的 Promise 实例的返回值,就传递给p的回调函数,p的状态就会改变Resolved状态。
即便只有一个是成功的状态,整体都会变成成功的状态
使用
主要应用场景我觉得是解决回调地狱而产生的。
基本例子
// 一个简单的例子
let func1 = () => {
return new Promise((resolve, reject) => {
// 改变状态 => 成功
resolve('OK')
// 改变状态 => 失败
reject('Fail')
})
}
func1().then(
success => {
console.log('success', success)
},
error => {
console.log('error', error)
}
)
上述打印输出的结果是
success OK
原因是执行resolve()的时候,Promise 的状态已经发生了变化,所以后面的再执行 reject() 也是无法再次改变状态的。
在 new Promise 的时候传入两个参数,分别代表成功和失败的回调函数。
在状态发送改变后,就会调用.then()绑定的函数,.then()包含两个函数,第一个是成功的回调,第二个是失败的回调。
进阶
现在有一个需求,也是我们项目中常见的需求:
先请求A数据 => 再根据A数据中的ID => 再去请求B数据 ...
如果用传统的方式实现的,就很容易陷入回调地狱,如果层级一旦多的话,那代码看得令人头皮发麻。
$ajax({
url: 'https:....',
success: function () {
$ajax({
url: 'https:....',
success: function () {
.....
}
})
}
})
现在改用 Promise 的方式实现一下一上需求
let func1 = () => {
return new Promise((resolve, reject) => {
// 改变状态 => 成功
resolve()
console.log('A数据')
// 改变状态 => 失败
reject('Fail')
})
}
let fun2 = func1().then(
success => {
return new Promise((resolve, reject) => {
resolve()
console.log('B数据')
})
}
)
fun2.then(
success => {
console.log('成功的回调')
}
)
上述代码运行后的结果是
A数据
B数据
成功的回调
这样就能保证能在 A 数据拿到的情况下才会去调用 B方法的请求。