声明:以下答案均为 deepSeep 输出
方法一:标志位控制
- 标志位控制:通过
hasToastShown
确保 toast 只弹出一次。 - 统一错误处理:使用
Promise.all
处理批量请求,在catch
中统一处理错误并弹出 toast。 - 重置标志位:在
finally
中重置标志位,以便下次请求可以再次弹出 toast
let hasToastShown = false;
function showToast(message) {
if (!hasToastShown) {
// 弹出 toast
Toast.show(message);
hasToastShown = true;
}
}
function handleBatchRequests(requests) {
Promise.all(requests)
.then(responses => {
// 处理成功响应
})
.catch(error => {
showToast("请求失败,请稍后重试");
})
.finally(() => {
// 重置标志位
hasToastShown = false;
});
}
方法二:防抖
通过防抖,将多次请求失败合为一次处理,确保在一定时间内只弹出一个 toast。
实现思路:
- 设置一个防抖函数,延迟执行toast弹出。
- 如果在延迟时间内有新的失败请求,取消之前的延迟并重新计时。
let toastTimeout = null;
function showToast(message) {
if (toastTimeout) {
clearTimeout(toastTimeout); // 取消之前的延迟
}
toastTimeout = setTimeout(() => {
Toast.show(message); // 弹出 toast
toastTimeout = null; // 重置计时器
}, 300); // 设置防抖时间(例如 300ms)
}
function handleBatchRequests(requests) {
Promise.all(requests)
.then(responses => {
// 处理成功响应
})
.catch(error => {
showToast("请求失败,请稍后重试");
});
}
方法三:队列管理
将失败请求放入队列中,统一处理队列中的失败请求,确保只弹出一个 toast。
实现思路:
- 维护一个失败请求队列。
- 当队列不为空时,弹出toast并清空队列。
let failedRequestsQueue = [];
function showToast(message) {
if (failedRequestsQueue.length > 0) {
Toast.show(message); // 弹出 toast
failedRequestsQueue = []; // 清空队列
}
}
function handleBatchRequests(requests) {
Promise.all(requests)
.then(responses => {
// 处理成功响应
})
.catch(error => {
failedRequestsQueue.push(error); // 将失败请求加入队列
showToast("请求失败,请稍后重试");
});
}
方法四:单例模式
- 创建一个单例的 toast 管理器,负责控制 toast 的弹出。
- 在批量请求失败时,调用单例管理器弹出 toast 。
class ToastManager {
constructor() {
this.isToastShown = false;
}
showToast(message) {
if (!this.isToastShown) {
Toast.show(message);
this.isToastShown = true;
setTimeout(() => {
this.isToastShown = false; // 重置状态
}, 3000); // 假设 toast 显示时间为 3 秒
}
}
}
const toastManager = new ToastManager();
function handleBatchRequests(requests) {
Promise.all(requests)
.then(responses => {
// 处理成功响应
})
.catch(error => {
toastManager.showToast("请求失败,请稍后重试");
});
}
方法五:全局状态管理
如果项目中使用状态管理工具(如 Redux、Vuex 等),可以通过全局状态控制 toast 的弹出。
实现思路:
- 在全局状态中维护一个
hasToastShown
状态。 - 在请求失败时,检查状态并决定是否弹出 toast。
// Action
function showToast(message) {
return (dispatch, getState) => {
const { hasToastShown } = getState();
if (!hasToastShown) {
dispatch({ type: "SHOW_TOAST", payload: message });
dispatch({ type: "SET_TOAST_SHOWN", payload: true });
setTimeout(() => {
dispatch({ type: "SET_TOAST_SHOWN", payload: false }); // 重置状态
}, 3000); // 假设 toast 显示时间为 3 秒
}
};
}
// Reducer
const initialState = {
hasToastShown: false,
};
function toastReducer(state = initialState, action) {
switch (action.type) {
case "SET_TOAST_SHOWN":
return { ...state, hasToastShown: action.payload };
default:
return state;
}
}
// 请求处理
function handleBatchRequests(requests) {
Promise.all(requests)
.then(responses => {
// 处理成功响应
})
.catch(error => {
store.dispatch(showToast("请求失败,请稍后重试"));
});
}
方法六:Promise 最终状态
在批量请求完成后,统一检查是否有失败请求,并弹出 toast。
实现思路:
- 使用
Promise.allSettled
获取所有请求的最终状态。 - 检查是否有失败的请求,并弹出 toast。
function handleBatchRequests(requests) {
Promise.allSettled(requests)
.then(results => {
const hasFailed = results.some(result => result.status === "rejected");
if (hasFailed) {
Toast.show("请求失败,请稍后重试");
}
});
}
总结
方法 | 优点 | 缺点 |
---|---|---|
标志位控制 | 简单直接,易于实现 | 需要手动重置标志位 |
防抖 | 避免短时间内多次弹出 toast | 需要设置合理的防抖时间 |
队列管理 | 灵活,适合复杂场景 | 需要额外维护队列 |
单例模式 | 确保全局唯一性,适合大型项目 | 需要额外实现单例逻辑 |
全局状态管理 | 适合使用状态管理的项目 | 依赖状态管理工具 |
Promise 最终状态 | 简单,适合批量请求的统一处理 | 无法实时响应失败请求 |