前端批量请求失败 Toast 重复弹窗怎么解决?

在前端开发的日常工作中,我们常常会遇到批量发送请求的场景,比如一次性提交多个表单数据、同时获取多个接口数据等。然而,当这些批量请求出现失败时,一个令人头疼的问题往往会随之而来 ——Toast 重复弹窗。想象一下,用户操作后,屏幕上接连不断地弹出相同的错误提示,不仅影响用户体验,还可能让用户感到困惑和烦躁。如果在面试中被问到这个问题,该如何优雅地给出解决方案呢?接下来,我们就深入探讨一下。​

一、问题现象与原因分析​

1.1 问题现象​

当我们发起批量请求时,由于网络延迟、接口异常等原因,多个请求可能同时失败。此时,如果没有对 Toast 的展示进行合理控制,页面上就会在短时间内重复弹出多个相同或相似的 Toast 提示,向用户传达请求失败的信息。这种情况不仅显得界面杂乱无章,还会让用户难以快速获取关键信息,甚至可能导致用户误操作。​

1.2 原因剖析​

出现 Toast 重复弹窗的核心原因在于,在批量请求的场景下,每个请求的失败回调函数都会独立触发 Toast 的展示逻辑。在 JavaScript 中,当我们使用 Promise.all 等方法批量发送请求时,一旦某个请求被 reject,对应的失败处理代码就会执行。如果在失败处理中直接调用 Toast 展示函数,而没有任何去重或控制机制,就会导致 Toast 多次弹出。例如:

const requests = [
    fetch('api1'),
    fetch('api2'),
    fetch('api3')
];

Promise.all(requests)
   .then(responses => {
        // 处理成功响应
    })
   .catch(error => {
        // 每个请求失败都会触发这里,直接调用Toast展示会导致重复弹窗
        showToast('请求失败,请稍后重试');
    });

二、解决方案​

2.1 使用标志位控制​

一种简单有效的方法是使用标志位来控制 Toast 的展示。在发起批量请求前,设置一个标志位表示 Toast 是否已经展示过。当第一个请求失败触发 Toast 展示时,将标志位设置为 true,后续其他请求失败时,先检查标志位,如果已经为 true,则不再重复展示 Toast。在 Toast 自动消失或用户手动关闭后,将标志位重新设置为 false。示例代码如下:

let isToastShown = false;
const requests = [
    fetch('api1'),
    fetch('api2'),
    fetch('api3')
];

Promise.all(requests)
   .then(responses => {
        // 处理成功响应
    })
   .catch(error => {
        if (!isToastShown) {
            showToast('请求失败,请稍后重试');
            isToastShown = true;
            // 假设Toast展示3秒后消失,3秒后重置标志位
            setTimeout(() => {
                isToastShown = false;
            }, 3000);
        }
    });

2.2 合并请求失败信息​

我们可以收集所有请求的失败信息,然后将这些信息合并成一个更全面的 Toast 提示进行展示。这样既能让用户了解到所有请求的失败情况,又避免了重复弹窗。可以通过定义一个数组来存储每个请求的失败信息,在所有请求都处理完成后,根据数组内容生成最终的 Toast 内容。示例代码如下:

const requests = [
    fetch('api1'),
    fetch('api2'),
    fetch('api3')
];
const errorMessages = [];

Promise.allSettled(requests)
   .then(results => {
        results.forEach(result => {
            if (result.status === 'fulfilled') {
                // 处理成功响应
            } else {
                errorMessages.push(result.reason.message);
            }
        });
        if (errorMessages.length > 0) {
            const combinedMessage = `请求失败:${errorMessages.join(', ')}`;
            showToast(combinedMessage);
        }
    });

2.3 使用队列管理 Toast 展示​

创建一个 Toast 展示队列,当请求失败需要展示 Toast 时,将 Toast 信息加入队列。同时,设置一个任务来检查队列,如果队列中有待展示的 Toast,就取出一个进行展示,展示完成后再从队列中移除。这样可以保证同一时间只有一个 Toast 在展示,避免了重复弹窗。示例代码如下:

const toastQueue = [];
const requests = [
    fetch('api1'),
    fetch('api2'),
    fetch('api3')
];

function showToastFromQueue() {
    if (toastQueue.length > 0) {
        const toastMessage = toastQueue.shift();
        showToast(toastMessage);
        // Toast展示完成后,继续展示队列中的下一个
        // 假设Toast展示3秒后消失,3秒后调用自身继续处理队列
        setTimeout(showToastFromQueue, 3000);
    }
}

Promise.all(requests)
   .then(responses => {
        // 处理成功响应
    })
   .catch(error => {
        toastQueue.push('请求失败,请稍后重试');
        if (toastQueue.length === 1) {
            showToastFromQueue();
        }
    });

三、总结与拓展​

解决前端批量请求失败 Toast 重复弹窗的问题,关键在于对 Toast 的展示进行合理的控制和管理。通过使用标志位、合并失败信息、队列管理等方法,我们可以有效地避免重复弹窗,提升用户体验。在实际项目中,我们还可以根据具体需求,对这些方案进行优化和拓展。例如,结合不同的 Toast 组件特性,实现更灵活的展示效果;或者在合并失败信息时,对错误类型进行分类处理,让用户获取更准确的信息。​

希望以上内容能够帮助大家在面试中从容应对该问题,也能在实际开发中更好地解决类似的前端交互问题。如果你在实践过程中有任何疑问,或者有更好的解决方案,欢迎在评论区留言交流!​

var set_book_id = this.options.form.getWidgetByName("set_book_id").getValue(); var period_name = this.options.form.getWidgetByName("period_name").getValue(); // 1. 创建PL/SQL调用字符串 var proCall = "declare " + "v_errbuf varchar2(20); " + "v_Retcode number; " + "begin " + "CUX_INV_MODULE_PKG.pro_inv_moudule_main(v_errbuf,v_Retcode," + set_book_id + ",'" + period_name + "'); " + "end;"; // 2. 创建自定义提示(兼容低版本) var createToast = function(message) { var toast = document.createElement('div'); toast.style.cssText = ` position: fixed; top: 20px; left: 50%; transform: translateX(-50%); background: rgba(0,0,0,0.7); color: white; padding: 10px 20px; border-radius: 4px; z-index: 9999; font-size: 14px; transition: opacity 0.3s; `; toast.innerText = message; document.body.appendChild(toast); return toast; }; // 3. 显示执行中提示 var progressToast = createToast('执行库存模型请求中...'); // 4. 异步执行核心操作 setTimeout(function() { try { // 5. 执行远程操作 var sql = 'SQL("CC_PROD","' + proCall.replace(/'/g, "\\'") + '",1,1)'; var result = FR.remoteEvaluate(sql); // 6. 移除加载提示 document.body.removeChild(progressToast); // 7. 显示完成提示(使用兼容性方法) FR.Msg.alert("提示", "库存模型请求执行完成"); } catch (e) { document.body.removeChild(progressToast); FR.Msg.alert("错误", "库存模型请求执行失败: " + e.message); } }, 0);由于这个过程CUX_INV_MODULE_PKG.pro_inv_moudule_main在Oracle数据库端需要4分钟执行才能完成,目前方式调用后,显示执行完成,但是程序没有调用成功,如何修改代码
最新发布
06-17
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

coder YU

您的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值