本文详解JavaScript中Promise类的四个静态方法:all、allSettled、race和any。通过具体代码示例,解析各方法的执行逻辑、结果返回格式及异常处理机制,帮助开发者根据业务需求选择合适的方法。
本文主要介绍Promise类方法的实际应用场景。关于Promise的基础用法,此处不再展开,此前已有文章详细阐述过Promise的核心逻辑实现。尽管Promise在日常开发中应用广泛,但随着ES11和ES12的发布,新增了两个相关语法特性。本文将简要说明这些新特性的用法,内容相对简单。
1. all
Promise.all方法接收一个数组作为参数,数组中可以包含多个Promise对象。该方法会等待所有传入的Promise状态都变为fulfilled(成功)后,才获取最终结果。最终结果是一个数组,其中包含了每个Promise resolve的值,且结果的顺序与传入数组中Promise的顺序保持一致,与执行时间无关。
const p1 = new Promise((resolve, reject) => {
const obj = { data: '11111' }
setTimeout(() => {
resolve(obj)
}, 3000)
})
const p2 = new Promise((resolve, reject) => {
const obj = { data: '22222' }
setTimeout(() => {
resolve(obj)
}, 2000)
})
const p3 = new Promise((resolve, reject) => {
const obj = { data: '33333' }
setTimeout(() => {
resolve(obj)
}, 1000)
})
Promise.all([p1, p2, p3]).then(result => {
console.log(result)
}).catch(err => {
console.log('err:', err)
})上述代码将在3秒后,在then方法中获取到最终结果,具体如下:

然而,all方法存在一个缺陷:如果数组中有一个Promise变为rejected(失败)状态,新返回的Promise会立即变为对应的reject状态。这意味着错误只能在catch中捕获,其他已经fulfilled状态的Promise的值将无法获取。因此,allSettled方法应运而生。
2. allSettled
allSettled是ES11(2020年)新增的API,即Promise.allSettled。
该方法会在所有Promise都有结果时(无论是fulfilled还是rejected),都会在then方法中返回最终结果:
const p1 = new Promise((resolve, reject) => {
const obj = { data: '11111' }
setTimeout(() => {
resolve(obj)
}, 3000)
})
const p2 = new Promise((resolve, reject) => {
const obj = { data: '22222' }
setTimeout(() => {
reject(obj)
}, 2000)
})
const p3 = new Promise((resolve, reject) => {
const obj = { data: '33333' }
setTimeout(() => {
resolve(obj)
}, 1000)
})
Promise.allSettled([p1, p2, p3]).then(result => {
console.log(result)
}).catch(err => {
console.log('err:', err)
})示例中传入了三个Promise,在2秒时p2变为rejected状态。即便如此,我们依然可以拿到结果,但result数组的结构有所变化,具体打印结果如下:

从打印结果可以看出,allSettled返回的是一个数组,数组中的每个元素对应一个Promise的结果对象。该对象包含status状态属性,以及对应的value值。
3. race
race意为竞技或赛跑,即谁先有结果就采用谁的结果。因此,result获取到的不是一个数组,而是最快resolve的那个Promise的结果值。
const p1 = new Promise((resolve, reject) => {
const obj = { data: '11111' }
setTimeout(() => {
resolve(obj)
}, 3000)
})
const p2 = new Promise((resolve, reject) => {
const obj = { data: '22222' }
setTimeout(() => {
resolve(obj)
}, 2000)
})
const p3 = new Promise((resolve, reject) => {
const obj = { data: '33333' }
setTimeout(() => {
resolve(obj)
}, 1000)
})
Promise.race([p1, p2, p3]).then(result => {
console.log(result)
}).catch(err => {
console.log('err:', err)
})控制台打印结果如下:

由于p3用时最短,因此result获取到的是p3 resolve出的结果值。但如果最快的Promise是reject状态呢?我们来看下面的情况:
const p1 = new Promise((resolve, reject) => {
const obj = { data: '11111' }
setTimeout(() => {
resolve(obj)
}, 3000)
})
const p2 = new Promise((resolve, reject) => {
const obj = { data: '22222' }
setTimeout(() => {
reject('出错了~~~')
}, 500)
})
const p3 = new Promise((resolve, reject) => {
const obj = { data: '33333' }
setTimeout(() => {
resolve(obj)
}, 1000)
})
Promise.race([p1, p2, p3]).then(result => {
console.log(result)
}).catch(err => {
console.log('err:', err)
})修改代码,将p2的时间设置为0.5秒,且状态为rejected。再次查看打印结果:

结果会直接被catch捕获。这表明,如果最快的Promise状态为rejected,后续其他Promise的resolve值将无法获取。如果我们希望获取最快的fulfilled状态的值,即忽略前面的reject状态,继续等待下一个resolve,该如何实现?这就引出了any方法。
4. any
const p1 = new Promise((resolve, reject) => {
const obj = { data: '11111' }
setTimeout(() => {
resolve(obj)
}, 3000)
})
const p2 = new Promise((resolve, reject) => {
const obj = { data: '22222' }
setTimeout(() => {
reject('出错了~~~')
}, 500)
})
const p3 = new Promise((resolve, reject) => {
const obj = { data: '33333' }
setTimeout(() => {
resolve(obj)
}, 1000)
})
Promise.any([p1, p2, p3]).then(result => {
console.log(result)
}).catch(err => {
console.log('err:', err)
})沿用之前的代码,将方法改为any,再次查看打印结果:

我们在1秒后获取到p3 resolve的结果,而p2的reject状态被忽略。那么,如果所有Promise都是rejected状态,它会如何处理?我们来看:
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('出错了111~~~')
}, 3000)
})
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('出错了222~~~')
}, 500)
})
const p3 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('出错了333~~~')
}, 1000)
})
Promise.any([p1, p2, p3]).then(result => {
console.log(result)
}).catch(err => {
console.log('err:', err, err.errors)
})打印结果如下:

此时会进入catch分支,并打印出错误信息。其中,err.errors属性中包含了各个Promise reject传递的错误信息,err是内部封装的错误提示。
至此,关于JavaScript中Promise类使用方法的介绍到此结束。如需了解更多JavaScript Promise相关内容,请搜索本站历史文章或继续浏览相关文章。感谢大家的支持!