面试题答案
一键面试使用Promise.allSettled优化API调用
- 代码示例:
const axios = require('axios'); const apiCalls = [ axios.get('https://api.example.com/data1'), axios.get('https://api.example.com/data2'), axios.get('https://api.example.com/data3') ]; Promise.allSettled(apiCalls) .then(results => { results.forEach((result, index) => { if (result.status === 'fulfilled') { console.log(`API ${index + 1}成功:`, result.value.data); } else { console.log(`API ${index + 1}失败:`, result.reason); } }); });
- 原理:
Promise.allSettled
会等待所有传入的Promise对象都被解决(无论是成功还是失败),然后返回一个新的Promise对象。- 这个新的Promise对象的结果是一个数组,数组中的每个元素对应于传入的Promise对象的结果,每个元素是一个对象,有
status
属性(值为fulfilled
或rejected
),如果status
是fulfilled
,还有value
属性保存成功的值;如果status
是rejected
,则有reason
属性保存失败的原因。
使用队列控制优化API调用
- 代码示例:
const axios = require('axios'); const apiQueue = [ () => axios.get('https://api.example.com/data1'), () => axios.get('https://api.example.com/data2'), () => axios.get('https://api.example.com/data3') ]; function processQueue(queue) { let index = 0; return new Promise((resolve, reject) => { function next() { if (index >= queue.length) { resolve(); return; } queue[index]() .then(result => { console.log(`API ${index + 1}成功:`, result.data); index++; next(); }) .catch(error => { console.log(`API ${index + 1}失败:`, error); reject(error); }); } next(); }); } processQueue(apiQueue);
- 原理:
- 将API调用函数放入一个队列中。
- 通过
processQueue
函数,每次只处理队列中的一个API调用,当前一个API调用完成(无论是成功还是失败),再处理下一个。这样可以控制并发量,避免因过多并发请求导致网络拥堵或资源耗尽。
优缺点分析
- Promise.allSettled的优点:
- 高效性:所有API调用同时发起,充分利用并行性,能在最短时间内获取所有数据(假设网络资源充足)。
- 全面反馈:能得到每个API调用的结果,无论是成功还是失败,便于统一处理和分析。
- Promise.allSettled的缺点:
- 资源消耗:如果同时发起过多API调用,可能会耗尽网络资源或导致应用程序响应变慢,特别是在网络环境较差时。
- 错误处理:当其中一个API调用失败时,不会立即停止所有调用,可能会导致不必要的资源浪费在后续可能失败的调用上。
- 队列控制的优点:
- 稳定性:通过控制并发量,能有效避免因过多请求导致的网络拥堵和资源耗尽,在网络不稳定或API性能较差时表现更稳定。
- 错误处理:当某个API调用失败时,可以根据需求选择立即停止后续调用,减少不必要的资源浪费。
- 队列控制的缺点:
- 效率问题:由于是顺序执行,整体获取数据的时间可能会比
Promise.allSettled
长,特别是在API响应时间较长且数量较多的情况下。 - 复杂度:代码实现相对复杂,需要手动管理队列和控制执行流程。
- 效率问题:由于是顺序执行,整体获取数据的时间可能会比