MST

星途 面试题库

面试题:复杂场景下Vue网络请求性能优化与请求合并策略设计

假设你正在开发一个大型的Vue电商应用,该应用包含商品列表展示、用户订单查询、购物车操作等多个模块,每个模块都有频繁的网络请求。请设计一套完整的网络请求性能优化与请求合并策略,涵盖如何根据业务场景动态调整优化策略,以及如何处理不同类型请求之间的依赖关系和优先级等问题,并结合代码示例说明。
12.8万 热度难度
前端开发Vue

知识考点

AI 面试

面试题答案

一键面试

网络请求性能优化策略

  1. 请求防抖与节流
    • 防抖:在短时间内多次触发同一请求时,防抖策略会等待一定时间(例如200ms),如果在这个等待时间内没有再次触发,则执行请求。如果再次触发,则重新计算等待时间。这适用于搜索框输入等场景,用户输入过程中会频繁触发查询请求,但我们希望在用户停止输入后再发起请求,以减少不必要的请求。
    • 节流:设定一个固定的时间间隔(例如500ms),在这个时间间隔内,无论触发多少次请求,只执行一次。这对于一些高频操作(如滚动加载更多商品)很有用,可以避免过于频繁的请求。
    • 代码示例(Vue中使用lodash的防抖和节流)
<template>
  <div>
    <input v-model="searchText" @input="debouncedSearch">
  </div>
</template>

<script>
import {debounce} from 'lodash';

export default {
  data() {
    return {
      searchText: '',
      searchResults: []
    };
  },
  methods: {
    async search() {
      // 实际的搜索请求逻辑
      const response = await fetch(`/api/search?query=${this.searchText}`);
      this.searchResults = await response.json();
    },
    debouncedSearch: debounce(function() {
      this.search();
    }, 200)
  }
};
</script>
  1. 缓存策略
    • 强缓存:利用HTTP的缓存头(如Cache - ControlExpires),对于不经常变化的数据(如商品分类数据),浏览器在缓存有效期内直接从本地缓存加载数据,而不向服务器发送请求。
    • 协商缓存:对于可能变化的数据(如商品价格),使用Last - ModifiedETag等头信息。浏览器先发送带有If - Modified - Since(值为上次获取数据的Last - Modified值)或If - None - Match(值为上次获取数据的ETag值)的请求,服务器根据这些头信息判断数据是否有更新。如果没有更新,返回304状态码,浏览器从本地缓存加载数据;如果有更新,返回新的数据。
    • 代码示例(设置缓存头在Node.js服务器端)
const express = require('express');
const app = express();

app.get('/api/categories', (req, res) => {
  // 设置强缓存,有效期1小时
  res.set('Cache - Control','max - age = 3600');
  // 返回商品分类数据
  res.json({categories: ['Electronics', 'Clothing', 'Food']});
});

app.get('/api/products/:id', (req, res) => {
  const product = getProductById(req.params.id);
  // 设置协商缓存
  res.set('ETag', product.etag);
  if (req.headers['if - none - match'] === product.etag) {
    res.status(304).send();
  } else {
    res.json(product);
  }
});

function getProductById(id) {
  // 实际的获取商品逻辑
  return {id: id, name: 'Sample Product', etag: '123456'};
}

const port = 3000;
app.listen(port, () => {
  console.log(`Server running on port ${port}`);
});
  1. 使用HTTP/2
    • HTTP/2具有多路复用、头部压缩等特性,可以显著提高网络性能。多路复用允许在同一个连接上同时发送多个请求和响应,避免了HTTP/1.1中的队头阻塞问题。头部压缩减少了请求和响应头部的大小,从而加快数据传输。
    • 部署:在服务器端配置支持HTTP/2。例如,在Nginx服务器中,可以通过以下配置启用HTTP/2:
server {
  listen 443 ssl http2;
  server_name your_domain.com;

  ssl_certificate /path/to/your_certificate;
  ssl_certificate_key /path/to/your_private_key;

  location / {
    proxy_pass http://your_backend_server;
  }
}

请求合并策略

  1. 按模块合并
    • 对于同一模块内的多个请求,如果这些请求可以合并成一个请求,就进行合并。例如,在商品列表展示模块中,可能需要获取商品基本信息、商品评论数量、商品销量等数据。可以设计一个接口,一次性返回这些数据,而不是分别发起多个请求。
    • 代码示例(假设使用Axios进行HTTP请求)
import axios from 'axios';

// 合并请求
async function getProductDetails(productId) {
  const response = await axios.get(`/api/products/${productId}/details`, {
    params: {
      include: 'comments_count,sales_count'
    }
  });
  return response.data;
}
  1. 依赖关系处理
    • 串行处理:当请求之间存在严格的依赖关系时,采用串行处理。例如,在用户订单查询模块中,可能需要先获取用户的登录信息,然后根据登录信息查询用户的订单。这种情况下,先发起获取登录信息的请求,在得到响应后再发起查询订单的请求。
    • 代码示例
async function getOrders() {
  const loginResponse = await axios.get('/api/user/login');
  const userId = loginResponse.data.userId;
  const ordersResponse = await axios.get(`/api/orders?userId=${userId}`);
  return ordersResponse.data;
}
  • 并行处理:当请求之间没有依赖关系时,可以并行发起请求,以提高效率。例如,在购物车操作模块中,同时获取购物车商品列表和促销活动信息,可以并行发起这两个请求。
  • 代码示例
async function getCartAndPromotions() {
  const [cartResponse, promotionsResponse] = await Promise.all([
    axios.get('/api/cart'),
    axios.get('/api/promotions')
  ]);
  return {cart: cartResponse.data, promotions: promotionsResponse.data};
}
  1. 优先级处理
    • 可以根据业务场景为不同类型的请求设置优先级。例如,对于购物车结算请求,优先级应该高于商品图片加载请求。在实现上,可以维护一个请求队列,按照优先级顺序处理请求。
    • 代码示例(简单的请求队列实现)
class RequestQueue {
  constructor() {
    this.queue = [];
  }

  addRequest(request, priority) {
    this.queue.push({request, priority});
    this.queue.sort((a, b) => b.priority - a.priority);
  }

  async processQueue() {
    while (this.queue.length > 0) {
      const {request} = this.queue.shift();
      await request();
    }
  }
}

// 使用示例
const queue = new RequestQueue();
queue.addRequest(() => axios.post('/api/checkout'), 10); // 结算请求,优先级10
queue.addRequest(() => axios.get('/api/product/image'), 5); // 商品图片请求,优先级5
queue.processQueue();

根据业务场景动态调整优化策略

  1. 用户网络状况
    • 使用navigator.connection API(在支持的浏览器中)来检测用户的网络类型(如wificellular)和网络质量(如effectiveType)。对于较差的网络状况(如2g网络),可以适当增加缓存的使用,减少请求频率,或者降低图片质量等资源的请求。
    • 代码示例
if ('connection' in navigator) {
  const connection = navigator.connection;
  connection.addEventListener('change', () => {
    if (connection.effectiveType === '2g') {
      // 增加缓存使用,减少请求
      // 例如,延长商品图片缓存时间
      // 或者降低图片请求的分辨率
    }
  });
}
  1. 业务流程阶段
    • 在不同的业务流程阶段,采用不同的优化策略。例如,在购物车结算阶段,确保结算请求的准确性和及时性,优先处理结算相关请求,并且对结算请求采用更高的优先级和更严格的请求验证。而在用户浏览商品阶段,可以更多地利用缓存和异步加载策略。
    • 代码示例(根据业务流程设置请求优先级)
// 假设处于结算流程
const isCheckout = true;
const queue = new RequestQueue();
if (isCheckout) {
  queue.addRequest(() => axios.post('/api/checkout'), 10);
  queue.addRequest(() => axios.get('/api/cart'), 5);
} else {
  queue.addRequest(() => axios.get('/api/products'), 5);
  queue.addRequest(() => axios.get('/api/promotions'), 5);
}
queue.processQueue();