如何正确地使用 Promise.allSettled
Promise.allSettled 是 ES2020 引入的一个新方法,它可以在一次性获取所有的 promise 结果,而不需要手动处理每一个 promise 结果。正确地使用 Promise.allSettled 可以大幅度提升代码的可读性和可维护性。
1. Promise.allSettled 的用途
Promise.allSettled 可以接收一个 promise 数组作为参数,返回的结果是一个 promise 对象。这个 promise 对象的状态只有两种:fulfilled 和 rejected。
无论是哪种状态,Promise.allSettled 都会把每个 promise 结果包装成一个对象,对象中包含三个属性:
- status(状态):'fulfilled' 或 'rejected'。
- value(结果值):如果 status 是 'fulfilled' 则为返回值,否则为错误信息。
- reason(失败原因):如果 status 是 'fulfilled' 则为 undefined,否则为错误信息。
// javascriptcn.com 代码示例 const promise1 = Promise.resolve(1); const promise2 = Promise.reject('error'); const promise3 = new Promise(resolve => setTimeout(resolve, 1000)); Promise.allSettled([promise1, promise2, promise3]).then(result => { console.log(result); }); // result // [ // { status: 'fulfilled', value: 1 }, // { status: 'rejected', reason: 'error' }, // { status: 'fulfilled', value: undefined }, // ]
2. Promise.allSettled 的优点
Promise.allSettled 和 Promise.all 有点相似,但 Promise.all 只有在所有 promise 都成功时才返回结果,如果任意一个 promise 失败,就直接 reject。这样的设计不够灵活,也不够实用。
Promise.allSettled 弥补了 Promise.all 的缺陷,不管成功或失败,它都会得到所有 promise 结果。这个特性非常适合在处理多个任务的情况下使用。
// javascriptcn.com 代码示例 const tasks = [task1(), task2(), task3()]; Promise.allSettled(tasks).then(results => { results.forEach(result => { if (result.status === 'fulfilled') { console.log(result.value); } else { console.log(result.reason); } }) });
3. Promise.allSettled 的几个注意点
3.1 兼容性
Promise.allSettled 是 ES2020 中引入的,在使用前需要先判断浏览器是否支持该特性。可以使用 Polyfill 方式进行兼容处理。
// javascriptcn.com 代码示例 if (!Promise.allSettled) { Promise.allSettled = function(promises) { return Promise.all(promises.map(promise => { return promise .then(value => { return { status: 'fulfilled', value }; }, reason => { return { status: 'rejected', reason }; }); })); }; }
3.2 allSettled 的执行顺序
Promise.allSettled 并不会在任务全部结束后才 resolve,而是无论结果如何,立即返回所有结果。这意味着在需要等待所有任务完成的情况下,需要使用 async/await 或者其他手段进行处理。
// javascriptcn.com 代码示例 const tasks = [task1(), task2(), task3()]; Promise.allSettled(tasks).then(results => { console.log('all tasks finished'); }); console.log('start tasks'); // output // start tasks // all tasks finished
3.3 allSettled 的内存问题
Note that the array returned by this function will not be freed even if the returned Promise is rejected.
在执行完 Promise.allSettled 后,返回的结果数组仍然会被保存在内存中,不管是否有 promise 失败,都是如此。因此,处理大量 promise 的情况下,可能会造成内存问题。
4. Promise.allSettled 的示例代码
以下是 Promise.allSettled 的一个示例代码,里面包含了多个异步请求的处理。
// javascriptcn.com 代码示例 // 封装请求,返回 Promise 结果 function request(url) { return new Promise((resolve, reject) => { const xhr = new XMLHttpRequest(); xhr.open('GET', url, true); xhr.onload = function() { resolve(JSON.parse(xhr.responseText)); }; xhr.onerror = function() { reject('Network error'); }; xhr.send(null); }); } // 异步请求实例 const request1 = request('http://example.com/api/data1'); const request2 = request('http://example.com/api/data2'); const request3 = request('http://example.com/api/data3'); // 处理异步请求结果 Promise.allSettled([request1, request2, request3]).then(results => { results.forEach(result => { if (result.status === 'fulfilled') { console.log(result.value); } else { console.log(result.reason); } }); }).catch(e => { console.log(e); });
5. 总结
正确使用 Promise.allSettled 可以大大提高代码的可读性和可维护性。但在使用过程中也需要注意兼容性、执行顺序和内存问题等方面。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65408dac7d4982a6eba0ed88