关于Promise,你了解的全面吗?含义 Promise是异步编程的一种解决方案,它可以看做一个容器,里面保存着某个异步
含义
Promise是异步编程的一种解决方案,它可以看做一个容器,里面保存着某个异步操作的结果,并且它解决了回调地狱的问题。 (1)三种状态:pending fulfilled rejected (2)状态变化不可逆 pending -> fulfilled(成功) pending -> rejected(失败)
基本用法
const p = new Promise(function(resolve, reject) {
if (/* 异步操作成功 */){
resolve(value)
} else {
reject('error')
}
})
p.then(funcion(value) {
// success
console.log(val)
}, function(error) {
// failure
console.log(error)
}
p.then((val) => {
console.log(val)
}).catch((err) => {
console.log(err)
})
简单说明下,resolve()只会触发then,reject()只会触发catch。
then 和 catch 改变状态
- then正常返回resolved,里面有报错则返回rejected
- catch正常返回resolved,里面有报错则返回rejected
const p = Promise.resolve().then(() => {
throw new Error('then error')
})
console.log(p) // 此时p是rejected状态,触发catch回调
const p2 = Promise.reject('error').catch((err) => console.log(err))
console.log(p2) // 此时p2是fulfilled状态,触发then回调
const p3 = Promise.reject('error').catch((err) => {
throw new Error('catch err')
})
console.log(p3) // 此时p3是rejected状态,触发catch回调
写到此处,分享几道面试题,答案可以通过上面的2句话很轻松的得出来
Promise.resolve().then(() => {
console.log(1)
}).catch(() => {
console.log(2)
}).then(() => {
console.log(3)
}) // 1 3
Promise.resolve().then(() => {
console.log(1)
throw new Error('error1')
}).catch(() => {
console.log(2)
}).then(() => {
console.log(3)
}) // 1 2 3
Promise.resolve().then(() => {
console.log(1)
throw new Error('error1')
}).catch(() => {
console.log(2)
}).catch(() => {
console.log(3)
}) // 1 2
其他常用的几个方法
- finally:不管Promise对象最后状态如何,都会执行的操作
promise
.then(result => {···})
.catch(error => {···})
.finally(() => {···})
- Promise.all()
const p = Promise.all([p1, p2, p3])
- 将多个Promise实例,包装成一个新的Promise实例,并发操作
- 状态分2种情况,第一所有状态都变成fulfilled,p的状态才变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数
- 第二只要有一个rejected,p的状态就变成rejected,此时第一个被rejected的实例的返回值,会传递给p的回调函数
const p1 = new Promise((resolve, reject) => {
resolve('hello')
}).then(result => result)
const p2 = new Promise((resolve, reject) => {
// throw new Error('报错了')
resolve('world')
}).then(result => result)
// rejected Error:报错了 fulfilled ['hello', 'world']
Promise.all([p1, p2]).then(result => console.log(result)).catch(e => console.log(e))
- Promise.race()
const p = Promise.race([p1, p2, p3])
只要p1、p2、p3中有一个实例率先改变状态,p的状态就跟着改变,那个率先改变的Promise实例的返回值,就传递给p的回调函数
- Promise.allSettled() 等一组异步操作都结束了,不管每一个操作是否成功还是失败,再进行下一步的操作
const promises = [ fetch('/api-1'), fetch('/api-2'), fetch('/api-3'),]
await Promise.allSettled(promises)
removeLoadingIndicator()
以上代码,只有等promises中的三个请求都结束了,才会执行removeLoadingIndicator方法 该方法返回新的Promise实例,一旦发生状态变更,状态总是fulfilled,不会变成rejected。状态变成fulfilled后,它的回调函数会接收到一个数组作为参数,该数组的每个成员对应前面数组的每个Promise对象
const resolved = Promise.resolve(42)
const rejected = Promise.reject(-1)
const allSettledPromise = Promise.allSettled([resolved, rejected])
allSettledPromise.then(function (results) {
console.log(results)
})
// [
// { status: 'fulfilled', value: 42 },
// { status: 'rejected', reason: -1 }
// ]
- Promise.any() 只要参数实例有一个变成fulfilled状态,包装实例就会变成fulfilled状态,如果所有参数实例都变成rejected状态,包装实例就会变成rejected状态。 与Promise.race()方法不同的是,Promise.any()不会因为某个Promise变成rejected状态而结束,必须等到所有参数Promise变成rejected状态才结束。
const resolved = Promise.resolve(42)
const rejected = Promise.reject(-1)
const alsoRejected = Promise.reject(Infinity)
Promise.any([resolved, rejected, alsoRejected]).then(function (result) {
console.log(result) // 42
})
Promise.any([rejected, alsoRejected]).catch(function (results) {
console.log(results instanceof AggregateError) // true
console.log(results.errors) // [-1, Infinity]
})
- Promise.resolve() 将现有对象转成Promise对象
Promise.resolve('foo')
// 等价于
new Promise(resolve => resolve('foo'))
const p = Promise.resolve('Hello');
p.then(function (s) {
console.log(s)
});
// Hello
- Promise.reject()
Promise.reject('出错了')
.catch(e => {
console.log(e === '出错了')
})
// true
- Promise.try() 捕获所有同步和异步的错误,catch只能捕获异步的错误,如果出现同步的异常,只能通过try catch去捕获,使用Promise.try()正好解决了这个问题
Promise.try(() => database.users.get({id: userId}))
.then(...)
.catch(...)
注:参考阮一峰ES6 Promise教程
转载自:https://juejin.cn/post/7410224960298778674