前端请求并发控制

266 阅读1分钟

一个小实现多个请求控制并发数量,同时一个请求执行完毕时自动执行下一个请求的demo。

vue:

<template>
  <div id="app">
    <div v-for="(item, index) in dataList" :key="index">第{{item}}个请求完成了</div>
  </div>
</template>
<script>
import Axios from 'axios';
let queue = [];
export default {
  name: 'App',
  data () {
    return {
      dataList: []
    }
  },
  created () {
    this.init();
  },
  methods: {
    getAsyncData (data) {
      return new Promise((resolve, reject) => {
        Axios.get(`/api/user?id=${data}`).then(result => {
          console.log(result, data);
          this.dataList.push(data)
          resolve();
        }).catch(function (error) {
          console.log(error);
          reject(error);
        })
      })
    },
    init () {
      const arr = [1,2,3,4,5,6,7,8,9,10];
      const promises = arr.map(item => this.getAsyncData.bind(this, item));
      this.asyncPool(4, promises);
    },
    asyncPool (limit, array) {
      if (array.length === 0) {
        // 清空容器
        queue = [];
        return Promise.resolve();
      }
      // 初始化容器
      queue = array.splice(0, limit - queue.length);
      // 执行容器中的请求
      const len = queue.length;
      for (let index = 0; index < len; index++) {
        if (queue[index] && typeof queue[index] === 'function') {
          queue[index]().then(() => {
            // 请求完成之后要把容器中的这个请求删除
            queue.splice(index, 1);
            // 之后重新将新请求放在容器中
            this.asyncPool(limit, array);
          })
        }
      }
    }
  },
}
</script>

模拟server:

const express = require('express');
const app = express();
app.get('/user', (req, res) => {
  // 模拟请求时间及返回
  const time = Math.random() * 10000;
  setTimeout(() => {
    res.send([
      {
        text: 1
      }, {
        text: 2
      }, {
        text: 3
      }, {
        text: 4
      }
    ]);
  }, time)
})
app.listen(3000, () => {
  console.log('success');
})

vue.config.js:

module.exports = {
  lintOnSave: false,
  devServer: {
    overlay: {
      warning: false,
      errors: false
    },
    proxy: {
      '/api': {
        target: 'http://localhost:3000',
        pathRewrite: {
          '^/api': '',
          ws: true,
          changeOrigin: true
        }
      }
    }
  },
}

附demo