- 作者:老汪软件技巧
- 发表时间:2024-09-10 11:01
- 浏览量:
作为一名资深前端专家,我经常需要处理并行任务,以提高开发效率和用户体验。今天,我将通过一个生活化的例子,展示如何使用JavaScript中的Promise来并行处理任务,并优雅地处理结果。
场景设定
想象一下,你的另一半给你分配了几个家务任务,每个任务都可以看作是一个Promise。你需要同时启动这些任务,并在所有任务结束后汇报工作结果。这不仅是一个生活技能,也是前端开发中常见的并行任务处理场景。
代码实现
我们首先定义了三个函数:cook、wash和sweep,每个函数返回一个Promise,模拟做饭、洗衣服和打扫卫生的过程。
// 做饭、洗衣服、打扫卫生的模拟函数
// 做饭
function cook() {
return new Promise((resolve, reject) => {
console.log('邓哥打开了电饭煲');
setTimeout(() => {
if (Math.random() < 0.5) {
resolve('饭已ok');
} else {
reject('做饭却忘了加水,米饭变成了爆米花');
}
}, 2000);
});
}
// 洗衣服
function wash() {
return new Promise((resolve, reject) => {
console.log('邓哥打开了洗衣机');
setTimeout(() => {
if (Math.random() < 0.5) {
resolve('衣服已经洗好');
} else {
reject('洗衣服时停水了,洗了个寂寞');
}
}, 2500);
});
}
// 打扫卫生
function sweep() {
return new Promise((resolve, reject) => {
console.log('邓哥打开了扫地机器人');
setTimeout(() => {
if (Math.random() < 0.5) {
resolve('地板扫的非常干净');
} else {
reject('扫地机器人被哈士奇一爪掀翻了');
}
}, 3000);
});
}
Promise的静态方法
在处理并行任务时,我们可以使用Promise的几种静态方法来控制任务的执行流程:
练习题
接下来,我们通过一个实际的练习题来加深理解。假设我们需要根据页码获取学生数据,并处理可能出现的错误。
// 获取学生数据的模拟函数
/**
* 根据页码获取学生数据,返回Promise
* @param {Number} page 页码
*/
function fetchStudents(page) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() < 0.3) {
reject(new Error(`网络错误!获取第${page}页数据失败!`));
return;
}
// 模拟学生数据
const stus = new Array(10).fill(null).map((d, i) => ({
id: `NO.${(page - 1) * 10 + i + 1}`,
name: `姓名${(page - 1) * 10 + i + 1}`,
}));
resolve(stus);
}, Math.floor(Math.random() * 5000));
});
}
// 利用 fetchStudents 函数,完成下面的练习
// 获取1-10页的学生,最终按照页码的顺序合并成一个数组,任何一页的数据获取出现错误,则任务不再继续,打印错误消息
Promise.all(proms)
.then((result) => {
console.log(result.flat());
})
.catch((err) => {
console.log(err);
});
// 获取1-10页的学生,最终按照页码的顺序合并成一个数组,如果某些页码的数据获取失败,就不加入该数据即可
Promise.allSettled(proms).then((result) => {
result = result
.filter((r) => r.status === 'fulfilled')
.map((it) => it.value)
.flat();
console.log(result);
});
// 获取1-10页的学生,打印最先获取到的数据,如果全部都获取失败,则打印所有的错误消息
Promise.any(proms)
.then((result) => {
console.log(result);
})
.catch((err) => {
console.log(err.errors);
});
// 获取1-10页的学生,输出最先得到的结果(有结果输出结果,有错误输出错误)
Promise.race(proms).then(
(result) => {
console.log(result);
},
(err) => {
console.log(err);
}
);
我们使用Promise.all、Promise.allSettled、Promise.any和Promise.race来处理不同情况下的数据获取。
场景解决方案
最后,我们将上述家务任务的解决方案实现如下:
// 并行执行家务任务并汇总结果
Promise.allSettled([cook(), wash(), sweep()]).then((result) => {
// 处理汇总结果
const report = result
.map((r) => (r.status === 'fulfilled' ? r.value : r.reason))
.join(';');
console.log(report);
});
结论
通过这个例子,我们可以看到Promise在并行任务处理中的强大能力。在工作中,合理利用Promise可以大大提高我们的效率和处理复杂问题的能力。