vue 多个请求要同时拉取数据,写一个方法

在 Vue 中实现多个请求同时拉取数据 ,核心是利用 JavaScript 的Promise.all(或Promise.allSettled等)方法,将多个异步请求(通常是axios/fetch请求)封装为 Promise 对象,实现并行请求,提升数据加载效率。以下是详细的实现方法和场景适配:

一、基础场景:所有请求成功才处理数据(Promise.all)

Promise.all会等待所有 Promise 都成功 resolve 后,才会返回结果数组;如果有一个请求失败(reject),则整体直接失败。适合多个请求缺一不可的场景(如页面初始化需要同时加载用户信息、商品列表、分类数据)。

步骤 1:封装请求函数(以 axios 为例)

首先定义需要并行执行的接口请求函数(也可直接在方法中写请求):

javascript 复制代码
// 引入axios(需先安装:npm install axios)
import axios from 'axios';

// 请求1:获取用户信息
const getUserInfo = () => {
  return axios.get('/api/user/info'); // 返回Promise对象
};

// 请求2:获取商品列表
const getGoodsList = () => {
  return axios.get('/api/goods/list');
};

// 请求3:获取分类数据
const getCategory = () => {
  return axios.get('/api/category');
};
步骤 2:在 Vue 组件中编写并行请求方法
javascript 复制代码
<template>
  <div v-if="loading">加载中...</div>
  <div v-else>
    <!-- 渲染数据 -->
    <div>用户信息:{{ userInfo }}</div>
    <div>商品列表:{{ goodsList }}</div>
    <div>分类数据:{{ category }}</div>
  </div>
</template>

<script>
import axios from 'axios';
// 引入上述请求函数(或直接在组件内定义)

export default {
  data() {
    return {
      loading: false,
      userInfo: null,
      goodsList: [],
      category: [],
      errorMsg: ''
    };
  },
  mounted() {
    // 页面挂载时执行并行请求
    this.fetchAllData();
  },
  methods: {
    // 核心:并行请求方法
    async fetchAllData() {
      this.loading = true;
      try {
        // 1. 将多个请求放入Promise.all,实现并行执行
        const [userRes, goodsRes, categoryRes] = await Promise.all([
          getUserInfo(), // 请求1
          getGoodsList(), // 请求2
          getCategory()   // 请求3
        ]);

        // 2. 处理每个请求的返回数据(根据接口返回结构调整)
        this.userInfo = userRes.data;
        this.goodsList = goodsRes.data.list;
        this.category = categoryRes.data;
      } catch (error) {
        // 3. 捕获任意一个请求的错误
        this.errorMsg = '数据加载失败:' + error.message;
        console.error('请求失败:', error);
      } finally {
        // 4. 无论成功失败,关闭加载状态
        this.loading = false;
      }
    }
  }
};
</script>

二、进阶场景:允许部分请求失败(Promise.allSettled)

如果希望即使部分请求失败,其他请求的结果仍能正常处理 (如加载商品详情时,推荐商品请求失败不影响主详情展示),使用Promise.allSettled,它会等待所有 Promise 都完成(无论成功 / 失败),返回每个请求的结果对象。

改造后的fetchAllData方法:

javascript 复制代码
async fetchAllData() {
  this.loading = true;
  try {
    // 1. 使用Promise.allSettled执行并行请求
    const results = await Promise.allSettled([
      getUserInfo(),
      getGoodsList(),
      getCategory()
    ]);

    // 2. 遍历结果,分别处理成功/失败的请求
    // 结果对象结构:{ status: 'fulfilled' | 'rejected', value: 成功数据 | reason: 失败原因 }
    results.forEach((result, index) => {
      switch (index) {
        case 0: // 第一个请求(用户信息)
          if (result.status === 'fulfilled') {
            this.userInfo = result.value.data;
          } else {
            console.error('用户信息请求失败:', result.reason);
            this.userInfo = {}; // 设默认值
          }
          break;
        case 1: // 第二个请求(商品列表)
          if (result.status === 'fulfilled') {
            this.goodsList = result.value.data.list;
          } else {
            console.error('商品列表请求失败:', result.reason);
            this.goodsList = [];
          }
          break;
        case 2: // 第三个请求(分类数据)
          if (result.status === 'fulfilled') {
            this.category = result.value.data;
          } else {
            console.error('分类数据请求失败:', result.reason);
            this.category = [];
          }
          break;
      }
    });
  } catch (error) {
    // 此处catch仅捕获Promise.allSettled本身的异常(极少出现,如参数非Promise)
    this.errorMsg = '请求处理异常:' + error.message;
  } finally {
    this.loading = false;
  }
}

三、补充说明

  1. 请求顺序问题Promise.all返回的结果数组顺序与传入的 Promise 顺序一致,与请求完成的先后无关(比如第二个请求先完成,结果仍在数组第二个位置)。

  2. 取消请求 :如果需要在组件销毁时取消未完成的请求,可使用 axios 的取消令牌(CancelToken) 或 Fetch 的AbortController,避免内存泄漏:

    javascript 复制代码
    // 示例:axios取消请求
    import axios from 'axios';
    
    export default {
      data() {
        return {
          cancelToken: axios.CancelToken.source() // 创建取消令牌
        };
      },
      methods: {
        async fetchAllData() {
          try {
            const [userRes, goodsRes] = await Promise.all([
              axios.get('/api/user/info', { cancelToken: this.cancelToken.token }),
              axios.get('/api/goods/list', { cancelToken: this.cancelToken.token })
            ]);
            // 处理数据
          } catch (error) {
            if (axios.isCancel(error)) {
              console.log('请求已取消:', error.message);
            } else {
              console.error('请求失败:', error);
            }
          }
        }
      },
      beforeDestroy() {
        // 组件销毁时取消请求
        this.cancelToken.cancel('组件已销毁,取消请求');
      }
    };

    并发限制 :如果需要并行的请求数量过多(如几十上百个),直接用Promise.all可能导致浏览器 / 服务器压力过大,可使用Promise 池 (如p-limit库)限制并发数:

    javascript 复制代码
    # 安装p-limit
    npm install p-limit
    javascript 复制代码
    import pLimit from 'p-limit';
    const limit = pLimit(5); // 限制同时最多5个请求
    
    // 批量请求示例(如10个商品详情请求)
    const goodsIds = [1,2,3,4,5,6,7,8,9,10];
    const requests = goodsIds.map(id => limit(() => axios.get(`/api/goods/${id}`)));
    const results = await Promise.all(requests);

    总结

  3. 简单场景(所有请求必须成功):用Promise.all

  4. 容错场景(允许部分请求失败):用Promise.allSettled

  5. 大量请求:用p-limit限制并发数;

  6. 组件销毁:记得取消未完成的请求,避免内存泄漏。

相关推荐
苏打水com2 小时前
第十篇:Day28-30 工程化优化与部署——从“能跑”到“好用”(对标职场“项目上线”需求)
前端·css·vue·html·js
写代码的皮筏艇2 小时前
react hooks中的useState
前端·javascript
fruge2 小时前
React Fiber 架构详解:为什么它能解决页面卡顿问题?
前端·react.js·架构
时72 小时前
iframe 事件无法冒泡到父窗口的解决方案
前端·element
用户6600676685392 小时前
纯 CSS 复刻星战开场:让文字在宇宙中滚动
前端·css
启山智软2 小时前
【单体系统与分布式系统是两种根本不同的软件架构模式】
java·vue.js·spring boot·后端·spring
AAA简单玩转程序设计2 小时前
Java里的空指针
java·前端
时72 小时前
PDF.js 在 Vue 中的使用指南
前端