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. 组件销毁:记得取消未完成的请求,避免内存泄漏。

相关推荐
前端小L1 小时前
双指针专题(三):去重的艺术——「三数之和」
javascript·算法·双指针与滑动窗口
0和1的舞者1 小时前
Spring AOP详解(一)
java·开发语言·前端·spring·aop·面向切面
web小白成长日记1 小时前
在Vue样式中使用JavaScript 变量(CSS 变量注入)
前端·javascript·css·vue.js
QT 小鲜肉1 小时前
【Linux命令大全】001.文件管理之which命令(实操篇)
linux·运维·服务器·前端·chrome·笔记
C_心欲无痕1 小时前
react - useImperativeHandle让子组件“暴露方法”给父组件调用
前端·javascript·react.js
霖鸣2 小时前
Minecraft通过kubejs进行简单魔改
javascript
JackieDYH3 小时前
HTML+CSS+JavaScript实现图像对比滑块demo
javascript·css·html
BullSmall3 小时前
支持离线配置修改及删除操作的实现方案
前端
全栈前端老曹4 小时前
【前端路由】Vue Router 嵌套路由 - 配置父子级路由、命名视图、动态路径匹配
前端·javascript·vue.js·node.js·ecmascript·vue-router·前端路由
EndingCoder4 小时前
安装和设置 TypeScript 开发环境
前端·javascript·typescript