2025场景面试题跟练(四)

48 阅读1分钟

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,如何保证批量请求失败,只弹出一个

  1. 使用promise.all
  2. 使用计数器拦截,每有一个请求+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));