面试题答案
一键面试Promise.all 使用场景及原因
- 资源并行加载:比如一个网页需要同时加载多个图片、脚本或者样式文件。假设网页有一个轮播图需要加载多张图片,代码如下:
const imgPromises = [
fetch('image1.jpg'),
fetch('image2.jpg'),
fetch('image3.jpg')
];
Promise.all(imgPromises)
.then(responses => {
// 所有图片都加载完成,可进行后续操作,如显示图片等
responses.forEach(response => {
// 处理每张图片的响应
});
})
.catch(error => {
// 只要有一个图片加载失败,就会进入这里
console.error('图片加载失败:', error);
});
原因是 Promise.all 会等待所有 Promise 都 resolve 后才会 resolve,确保所有资源都成功加载后再进行统一处理。如果有任何一个 Promise 被 reject,整个 Promise.all 就会被 reject,能及时发现加载过程中的错误。
- 多个异步任务并发执行且都要获取结果:例如在一个电商应用中,需要同时获取用户的订单列表、购物车信息以及用户积分信息,这些操作都是异步的,而且都需要获取结果来渲染页面。
const orderPromise = fetch('/api/orders');
const cartPromise = fetch('/api/cart');
const pointsPromise = fetch('/api/points');
Promise.all([orderPromise, cartPromise, pointsPromise])
.then(([orders, cart, points]) => {
// 可以根据获取到的订单、购物车和积分信息渲染页面
})
.catch(error => {
// 只要有一个请求失败,就捕获错误
console.error('获取数据失败:', error);
});
因为我们需要所有数据都获取到才能进行下一步操作,Promise.all 适合这种需要等待所有任务完成并获取所有结果的场景。
Promise.race 使用场景及原因
- 限时操作:比如在登录场景中,发送登录请求后,希望在一定时间内得到响应,如果超过这个时间没有响应,则提示用户网络可能有问题。
const loginPromise = fetch('/api/login');
const timeoutPromise = new Promise((_, reject) => {
setTimeout(() => {
reject(new Error('登录请求超时'));
}, 5000); // 5 秒超时
});
Promise.race([loginPromise, timeoutPromise])
.then(response => {
// 如果登录请求在 5 秒内完成,则进入这里处理响应
})
.catch(error => {
// 如果超时,或者登录请求失败,都会进入这里
console.error(error.message);
});
原因是 Promise.race 只要有一个 Promise 先 resolve 或者 reject 就会返回,在这里可以利用它来实现限时功能,一旦超时的 Promise 先 reject,就可以捕获到超时错误。
- 竞争资源:在分布式系统中,多个节点同时尝试获取某个共享资源(例如锁)。先获取到资源的节点继续执行后续操作,其他节点则进行相应处理。
const node1Promise = fetch('/api/lock?node=1');
const node2Promise = fetch('/api/lock?node=2');
const node3Promise = fetch('/api/lock?node=3');
Promise.race([node1Promise, node2Promise, node3Promise])
.then(response => {
// 先获取到锁的节点处理响应
})
.catch(error => {
// 所有节点获取锁都失败的情况
console.error('获取锁失败:', error);
});
Promise.race 能快速确定哪个节点先成功获取到资源,适用于这种竞争资源的场景。