Demo 地址

先上 demo 地址

https://codepen.io/firstblood...

我的项目背景

随着 面向领导编程 越来越深入人心, 看板 我的项目想必是每个前端开发专家的必修之路

产品经理 张三 要求 前端开发专家 红盾 做一个由 1000个图表定时刷新 的公司最新的财务收入状况

红盾chrome 上 一顿操作猛如虎,没两三天就把 我的项目搞定了 交付给产品经理 张三.

无并发管制

让咱们来看看 红盾 此时大抵的代码状况

<template>  <div class="app-container">    <div class="charts">      <div v-for="item in domList" :id="item" :key="item" class="chart" />    </div>  </div></template><script>const echarts = require("echarts");const chartNum = 1000; // 图表数量const chartIntervalTime = 2000; // 图表定时渲染毫秒数export default {  data() {    return {      domList: [],      chartObjs: {},      chartData: [150, 230, 224, 218, 135, 147, 260],    };  },  mounted() {    // 创立echart并绘图    this.createChart();    // 隔3秒更新图表数据并渲染    this.intervalChartData(chartIntervalTime);  },  methods: {    // 创立echart并绘图    async createChart() {      for (let i = 1; i <= chartNum; i++) {        this.domList.push("chart" + i);      }      this.$nextTick(this.renderChartList);    },    async renderChartList() {      this.domList.forEach((dom) => this.initChart(dom));    },    // 隔3秒更新图表数据并渲染    intervalChartData(s) {      setInterval(() => {        this.renderChartList();      }, s);    },    // 初始化图表    initChart(domId) {      if (!this.chartObjs[domId]) {        this.chartObjs[domId] = echarts.init(document.getElementById(domId));      }      const option = {        xAxis: {          type: "category",          data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],        },        yAxis: {          type: "value",        },        series: [          {            data: this.chartData,            type: "line",          },        ],      };      this.chartObjs[domId].clear();      this.chartObjs[domId].setOption(option);    },  },};</script><style scoped>.chart {  float: left;  width: 360px;  height: 300px;  margin: 10px;  border: 2px solid #ff9900;}</style>

后果 张三 不按套路出牌, 在电视机上偷偷安了个 浏览器(性能极差),而后输出地址 xxx.com (自行脑补)...

间接把浏览器给淦奔溃了...没错, 红盾 此时的心田

这时候 他想起了 后端大佬 老黄,老黄给了他一个思路 管制并发

实现管制并发

实现并发

  1. 首先咱们来实现一个管制并发函数

想间接进入主题的同学能够间接跳到 残缺代码 查看

/** * @params {Number} poolLimit -最大并发限度数 * @params {Array} array -所有的并发申请|渲染数组 * @params {Function} iteratorFn -对应执行的并发函数(承受 array 的每一项值) */async function asyncPool(poolLimit, array, iteratorFn) {  const ret = [] // 所有执行中的 promises  let executing = [] // 正在执行中的 promises  for (const item of array) {    //承受 iteratorFn 的返回值:Promise    const p = Promise.resolve().then(() => iteratorFn(item))    ret.push(p)    // 如果执行的数组 大于等于 最大并发限度 那么咱们就要管制并发    if (array.length >= poolLimit) {      const e = p.then(() => executing.splice(executing.indexOf(e), 1))      // p.then 返回的 一个Promise 咱们把它放到正在执行数组中,一旦执行完 便剔除对应的值      executing.push(e)      //外围代码:正在执行的 promises 数组 大于等于 `最大并发限度` 用.race 办法开释一个执行最快的      if (executing.length >= poolLimit) await Promise.race(executing)    }  }  //返回一个 Promise.all  return Promise.all(ret)}
  1. 革新 renderChartList 函数(外围)

    async renderChartList() {  // 这里的 MAX_CURRENT 之后能够自定义一个数字  await asyncPool(MAX_CURRENT, this.domList, (dom) => { // 咱们在这里必须返回一个 promise 对应为 `并发函数` 的 `p` 变量 return new Promise(async (resolve) => {   const res = await this.initChart(dom);   resolve(res);// 这一步之后, 对应执行 `并发函数` 的 p.then 剔除 }).then((data) => {   console.log(data);   return data; });  });}

3.革新 initChart 函数

咱们必须保障一个图表渲染实现,再执行下一个渲染,此时咱们就须要监听 Echartsfinished 事件

initChart(domId) {  // 咱们 把它革新成一个 promise 函数  return new Promise((resolve) => {    ...    // 外围代码 监听 echarts 的 finished    this.chartObjs[domId].on("finished", () => {      resolve(domId);// 对应 上一步的 `const res = await this.initChart(dom);`    });  });}

4.革新 intervalChartData 函数

咱们必须保障并发执行完 所有的图表渲染,再进入下一个定时器逻辑
判断 executing的长度即可(此时应该把 executing 独立为全局变量)

intervalChartData(s) {  setInterval(() => {    if (executing.length > 0) return; // 还有正在执行的渲染 不反复增加    this.renderChartList();  }, s);}

残缺代码

附上残缺代码

<template>  <div class="app-container">    <div class="charts">      <div v-for="item in domList" :id="item" :key="item" class="chart" />    </div>  </div></template><script>const echarts = require("echarts");const chartNum = 1000; // 图表数量const MAX_CURRENT = 50; // 图表最大渲染并发数const chartIntervalTime = 2000; // 图表定时渲染毫秒数let executing = [];/** * @params {Number} poolLimit -最大并发限度数 * @params {Array} array -所有的并发申请|渲染数组 * @params {Function} iteratorFn -对应执行的并发函数(承受 array 的每一项值) */async function asyncPool(poolLimit, array, iteratorFn) {  const ret = []; // 所有执行中的 promises  executing = []; // 正在执行中的 promises  for (const item of array) {    const p = Promise.resolve().then(() => iteratorFn(item));    ret.push(p);    if (array.length >= poolLimit) {      const e = p.then(() => executing.splice(executing.indexOf(e), 1));      executing.push(e);      if (executing.length >= poolLimit) await Promise.race(executing);    }  }  return Promise.all(ret);}export default {  data() {    return {      domList: [],      chartObjs: {},      chartData: [150, 230, 224, 218, 135, 147, 260],    };  },  mounted() {    // 创立echart并绘图    this.createChart();    // 隔3秒更新图表数据并渲染    this.intervalChartData(chartIntervalTime);  },  methods: {    // 创立echart并绘图    async createChart() {      for (let i = 1; i <= chartNum; i++) {        this.domList.push("chart" + i);      }      this.$nextTick(this.renderChartList);    },    async renderChartList() {      const res = await asyncPool(MAX_CURRENT, this.domList, (i, arr) => {        return new Promise(async (resolve) => {          const res = await this.initChart(i);          resolve(res);        }).then((data) => {          console.log(data);          return data;        });      });    },    // 隔3秒更新图表数据并渲染    intervalChartData(s) {      setInterval(() => {        if (executing.length > 0) return; // 还有正在执行的渲染 不反复增加        this.renderChartList();      }, s);    },    // 初始化图表    initChart(domId) {      return new Promise((resolve) => {        if (!this.chartObjs[domId]) {          this.chartObjs[domId] = echarts.init(document.getElementById(domId));        }        const option = {          xAxis: {            type: "category",            data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],          },          yAxis: {            type: "value",          },          series: [            {              data: this.chartData,              type: "line",            },          ],        };        this.chartObjs[domId].clear();        this.chartObjs[domId].setOption(option);        this.chartObjs[domId].on("finished", () => {          resolve(domId);        });      });    },  },};</script><style scoped>.chart {  float: left;  width: 360px;  height: 300px;  margin: 10px;  border: 2px solid #ff9900;}</style>

小彩蛋

小彩蛋✌️, 红盾压服张三买了个高性能的电视机 完满解决...

如有不对,欢送斧正 感觉有帮忙,欢送三连