
完成工作中遇到的完成过程: 超过50个页面导入数据会卡住,然后产品经理让我限制在只允许导入50个以内的数据,否则会报错。 将发布改为正式环境后,用户觉得将文档分成几个太麻烦了。例如,如果他们想导入300多个数据,他们必须将原始数据excel文件分成7个,一个一个导入,用户体验差。 于是这次迭代让我解除只允许导入50条的限制,想办法给导入加个进度条,让用户在等待的冗长时间里能感受到导入正在进行。
但问题是,导入是调整后端接口,只有在执行开始时才能进入pending状态,然后一直pending要求成功或失败后才会返回结果,因此制作进度条是不现实的(除非它是浏览器中永远无法读取的加载条,但仅仅提高用户体验是毫无意义的)。
那么如何才能更好地完成这一需求呢?由于导入不超过50个不会特别卡住,所以当导入超过50个数据时,我们分批进入,每50个数据调用一个接口,并在请求成功或失败时提示用户N到第一n 50条数据导入成功/失败】,就能更好的完成原定需求并提升用户体验度。
如果后端同事愿意合作,可以让他帮忙在导入前写一个数据验证接口,比如在导入200个数据之前,先验证这200个数据填写的格式是否正确,否则直接导入请求执行到一半,用户也应该抱怨(推锅)。 但是,根据项目分配,也可以编写验证前端。
回到主题:如果您想完成上述操作,即如果您不知道要传输的数据有多大,您必须在执行50个批导入请求之前不能插入下一个批导入请求,否则导入的数据将是混乱的。 但请求是异步的,我们需要解决的是按顺序执行循环导入的异步请求。for index循环执行方法不可避免地要求异步,因此写入递归执行请求不仅可以实现需求,而且比其他方法更方便。
// 分批导入仪器 recursionMeterImport(arr, index, otherArr, otherIndex) {
// arr分批导入的数据数组,index是递归时导入的第几批数组。otherArr执行当前递归后执行的下一类数组,otherIndex同上。 // 首先判断arr如果是空的,则执行导入请求,如果是空的,则开始导入下一类数据 if (arr.length) {
this.importInfo = "\n" `正在导入第${
index * 50 1}条至第${
(index 1) * 50}条数据...`; ajax.post("xxxx(批量导入接口)", arr[index]) .then((res) => {
this.importInfo = "\n" res.data.message; // 后端返回的提示信息,【XX条数据导入成功 if (res.data.body && res.data.body.length > 0) {
res.data.body.forEach((item, i) => {
this.importInfo += "\n" + `【${
index * 50 + i + 1}】:` + item; // 批量导入时每天数据的导入返回提示信息 }); } if (arr.length > index + 1) {
// 导入的不是最后一批数据,递归执行导入下一批数据 this.recursionMeterImport(arr, index + 1, otherArr, otherIndex); } else {
// 导入完数组的最后一批数据后,执行下一种类数据的递归导入 this.importInfo += "\n" + this.lang.ImportingMeterGroupStandardValue + "..."; // 提示开始导入下一种类数据 this.recursionMetergroupImport(otherArr, otherIndex); } }) .catch(() => {
this.$alert( "网络波动原因或未知错误导致导入失败,请重试或联系系统管理员!", this.lang.Tips ); this.btnDisabled = false; }); } else {
this.importInfo += "\n" + "仪表导入对标值内容为空"; this.importInfo += "\n" + this.lang.ImportingMeterGroupStandardValue + "..."; this.recursionMetergroupImport(otherArr, otherIndex); } }, // 递归分批导入仪表分组 recursionMetergroupImport(arr, index) {
// 下一种类的递归导入,基本同上,不再赘述 if (arr.length) {
this.importInfo += "\n" + `正在导入第${
index * 50 + 1}条至第${
(index + 1) * 50}条数据...`; ajax.post("xxxx(下一种类批量导入接口)", arr[index]) .then((res) => {
this.importInfo += "\n" + res.data.message; if (res.data.body && res.data.body.length > 0) {
res.data.body.forEach((item, i) => {
this.importInfo += "\n" + `【${
index * 50 + i + 1}】:` + item; }); } if (arr.length > index + 1) {
// 导入的不是最后一批数据,继续执行递归 this.recursionMetergroupImport(arr, index + 1); } else {
this.importInfo += "\n" + "对标值已全部导入成功!"; this.$alert("对标值已全部导入成功!", this.lang.Tips); this.search(); this.btnDisabled = false; } }) .catch(() => {
this.$alert( "网络波动原因或未知错误导致导入失败,请重试或联系系统管理员!", this.lang.Tips ); this.btnDisabled = false; }); } else {
this.importInfo += "\n" + "仪表分组导入对标值内容为空"; this.importInfo += "\n" + "对标值已全部导入成功!"; this.$alert("对标值已全部导入成功!", this.lang.Tips); this.search(); this.btnDisabled = false; } },
数组切割的方法请见我上一篇文章:JS将一个数组切割成同等大小的多个数组的方法
小记:刚听到一个不合理的需求时先不要急,和产品经理说明不合理的地方并提供自己的想法,有时他会觉得你的方案更好并采用,在动手完成的过程中跟着自己的思路走就能迎刃而解,事半功倍。 THX~