前言
Promise是ES6中的提供的一个异步解决方案,主要是想用来解决异步调用回调的问题,它是一个链式的操作,在实际开发过程中其实有很多的地方都用到了promise,比如fetch api返回的就是一个promise对象,generator中的yield一般也会跟promise对象,ES8中的async await是promise和generator函数的封装,所以还是很有必要对promise有一个深入的了解。
基础
promise是一个异步操作返回的结果,它有三种状态,pending(等待),resolve(成功),reject(失败),状态只能由pending变为resolve或者rejecjt,并且是不可逆的, 一旦执行,也是不可停止的。
基本用法
promise支持链式调用,使用then方法接收resolve的操作,catch方法接收reject的操作,对应链式调用,必须在上一个then方法中返回一个promise对象
new Promise((resolve, reject) => {
setTimeout(() => {
if(true) {
resolve('success')
} else {
reject('error')
}
},2000)
}).then(data => {
// 成功resolve
console.log(data)
return new Promise(() => {
resolve('ok')
})
}).then(data => {
console.log(data)
})catch(err => {
// 失败reject
console.log(err)
})
Promise必须传递一个函数作为参数,否则会报错
实例方法
promise对象中提供了三个常用的实例方法:then, catch, finally
then
promise中调用resolve时触发的方法, 一般情况下是成功时的处理
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('success')
},2000)
}).then(data => {
console.lgo(data)
})
catch
promise中调用reject时触发的方法,一般情况下是异常时的处理,对于reject(),需要使用catch进行捕获,不然浏览器会有错误的提示,一个未捕获的错误
new Promise((resolve, reject) => {
setTimeout(() => {
reject('error')
},2000)
}).catch( err => {
console.log(err)
})
finally
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('success')
},2000)
}).finally(() => {
console.log('finally')
})
promise中不管状态如何变化,最终都会执行finally
静态方法
resolve
// 传递对象
const p1 = Promise.resolve({title: 'hello world'})
p1.then(data => {
console.log(data) // {title: 'hello world'}
})
// 传递对象包括then方法
const thenObj = {
then: () => {
console.log('hello world') // 直接输出
}
}
Promise.resolve(thenObj)
- 执行resolve后,会返回一个promise对象,在调用对象的then方法时,resolve中的参数会传递给then方法作为参数
- 如果resolve的参数对象中有then方法,则会直接执行then方法
- 如果resolve的参数传递的是一个promise对象,则直接返回
reject
与resolve方法类似,只不过调用reject后,是触发catch方法进行逻辑处理,如果reject参数对象中有catch方法,则不会向上面场景中的then方法被直接执行
all
Promise.all方法中传递的是一个数组,返回的是一个promise对象
数组的每个值都是一个promise对象,只有等待当每个promise对象中都执行了resolve方法后,才会触发then方法,只要有一个promise执行了reject,那么就会触发catch, 永远也不会触发then方法了
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('p1')
}, 2000)
})
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('p2')
}, 3000)
})
Promise.all([p1, p2]).then(data => {
console.log(data)
}).catch(err => {
console.lgo(err)
})
race
与all用法类似,Promise.race方法中传递的是一个数组,返回的是一个promise对象
只要数组中某个promise对象执行了resolve或者reject,那么就会触发对应的then或catch方法,其他promise对象的结果都会被丢弃掉
简单来说race只对最先有结果(不管结果是成功还是失败)的promise进行处理,其他的一律不管
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('p1')
}, 2000)
})
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('p2')
}, 3000)
})
const p3 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('p3')
}, 1000)
})
Promise.race([p1, p2, p3]).then(data => {
console.log(data)
}).catch(err => {
console.lgo(err)
})
错误捕获
catch
当promise中执行reject时,可以通过catch方法捕获
new Promise((resolve, reject) => {
setTimeout(() => {
reject('error')
}, 2000)
}).then(data => {
console.log(data)
}).catch(err => {
console.log(err) // 捕获reject的信息
})
unhandledrejection
除了通过catch对每个promise进行单独捕获,还可以通过unhandledrejection进行全局的错误捕获,但catch存在时,unhandledrejection不会被监听到
new Promise((resolve, reject) => {
setTimeout(() => {
reject('error')
}, 2000)
}).then(data => {
console.log(data)
})
// 监听到promise的reject操作
window.addEventListener("unhandledrejection", (err) => {
console.log(err)
})