1. 防止前端页面重复请求
高频触发:用防抖或节流
function debounce(fn, delay) {
let timer;
return function (...args) {
clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, args);
}, delay);
};
}
// 使用示例
const fetchData = () => {
console.log('发送请求');
// 实际的 API 调用
};
const debouncedFetch = debounce(fetchData, 300);
button.addEventListener('click', debouncedFetch);
单次请求:用锁机制或 AbortController(如表单提交)
let isRequesting = false;
async function fetchData() {
if (isRequesting) {
console.log('请求进行中,请稍候');
return;
}
try {
isRequesting = true;
const response = await fetch('https://api.example.com/data');
const data = await response.json();
console.log(data);
} catch (error) {
console.error('请求失败', error);
} finally {
isRequesting = false; // 释放锁
}
}
button.addEventListener('click', fetchData);
let controller = null;
async function fetchData() {
// 取消上一次请求
if (controller) {
controller.abort();
}
controller = new AbortController();
const signal = controller.signal;
try {
const response = await fetch('https://api.example.com/data', { signal });
const data = await response.json();
console.log(data);
} catch (error) {
if (error.name === 'AbortError') {
console.log('请求被取消');
} else {
console.error('请求失败', error);
}
}
}
button.addEventListener('click', fetchData);
重复参数:用请求去重(如相同数据的查询)
const requestCache = new Map();
async function fetchData(params) {
const key = JSON.stringify(params); // 用参数生成唯一标识
if (requestCache.has(key)) {
console.log('重复请求,已阻止');
return requestCache.get(key); // 返回缓存结果或 Promise
}
try {
const response = await fetch(`https://api.example.com/data?${new URLSearchParams(params)}`);
const data = await response.json();
requestCache.set(key, data);
return data;
} catch (error) {
console.error('请求失败', error);
}
}
// 使用
fetchData({ id: 1 }).then(console.log);
fetchData({ id: 1 }); // 会被阻止
2. Resizeobserver作用是什么
当observer元素大小发生改变,允许你通过callback进行处理,比如响应式布局,比3D场景重新渲染画布
3. 如何还原用户操作流程
使用rrweb进行记录,当触发问题后,将前后操作上传服务器,之后用rrweb player播放出来
4.请求失败会弹出一个toast,如何保证批量请求失败,只弹出一个
- 使用promise.all
- 使用计数器拦截,每有一个请求+1,请求结束归0后才抛出错误
5.如何减少项目里面if-else
使用对象映射
function getMessage(status) {
if (status === 'success') {
return '操作成功';
} else if (status === 'error') {
return '操作失败';
} else if (status === 'loading') {
return '加载中';
} else {
return '未知状态';
}
}
// ===========================
const statusMessages = {
success: '操作成功',
error: '操作失败',
loading: '加载中'
};
function getMessage(status) {
return statusMessages[status] || '未知状态';
}
使用策略模式(Strategy Pattern)
将每个条件分支封装成独立的函数或类,适用于复杂逻辑。
function processPayment(method, amount) {
if (method === 'credit') {
return `信用卡支付 ${amount} 元`;
} else if (method === 'paypal') {
return `PayPal 支付 ${amount} 元`;
} else if (method === 'cash') {
return `现金支付 ${amount} 元`;
} else {
throw new Error('未知支付方式');
}
}
// =======================
const paymentStrategies = {
credit: (amount) => `信用卡支付 ${amount} 元`,
paypal: (amount) => `PayPal 支付 ${amount} 元`,
cash: (amount) => `现金支付 ${amount} 元`
};
function processPayment(method, amount) {
const strategy = paymentStrategies[method];
if (!strategy) throw new Error('未知支付方式');
return strategy(amount);
}
使用函数式组合或管道
function formatPrice(value, currency) {
if (currency === 'USD') {
return `$${value.toFixed(2)}`;
} else if (currency === 'EUR') {
return `€${value.toFixed(2)}`;
} else {
return `${value.toFixed(2)}`;
}
}
// ==========
const formatters = {
USD: value => `$${value}`,
EUR: value => `€${value}`,
default: value => `${value}`
};
const toFixed = value => value.toFixed(2);
const formatPrice = (value, currency) =>
(formatters[currency] || formatters.default)(toFixed(value));