问题

项目loading是统一封装的,发请求前会showLoading,请求完了会hideLoading。 但是,并发两个或者更多请求的时候,最短耗时的请求回来了,就会关闭loading, 预期是最后一个请求回来才能hideLoading,要怎么办?

复现场景

点我在线预览

<body>
  <div id="app">
    <h3>请求成功列表</h3>
    <ul>
      <li v-for="item in list ">
        第【】个请求回来了,耗时【】
      </li>
    </ul>
  </div>
</body>

<script>
  const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));

  const randomMs = () => Math.random() * 5000;

  const LoadingService = {
    _loadingInstance: null,
    show() {
      this._loadingInstance = ELEMENT.Loading.service({
        fullscreen: true,
        background: "rgba(0, 0, 0, 0.7)",
        text: "Loading"
      });
    },
    hide() {
      this._loadingInstance && this._loadingInstance.close();
    }
  };

  const api = {
    async getData(i, time) {
      LoadingService.show();
      await sleep(time);
      LoadingService.hide();
    }
  };

  const vm = new Vue({
    el: "#app",
    data() {
      return {
        list: []
      };
    },
    created() {
      for (let i = 0; i < 10; i++) {
        const time = randomMs();
        api.getData(i + 1, time).then(() => {
          this.list.push({ count: i + 1, time });
        });
      }
    }
  });
</script>

优化思路一: 防抖

LoadingServicehide方法做防抖处理,间隔给1000

LoadingService.hide = _.debounce(function() {
  this._loadingInstance && this._loadingInstance.close();
}, 1000);

但是,结果并没有达到预期,如果上一个请求话费跟下一个请求的回来的间隔大于1000还是不能符合预期

点进去多刷新几次试试。 点我在线预览

结论:用防抖来优化,不能很好的达到效果,防抖的间隔不好确定。

优化思路二:栈

每次LoadingService.show方法调用的时候,往栈里面push一个实例。 同样的每次在LoadingService.hide方法调用的时候,从栈里取出最前面的一个实例,当栈的长度是0的时候,说明没有正在进行中的请求了,这时候才可以去关闭loading

const LoadingService = {
  _loadingStack: [],
  show() {
    const loadingInstance = ELEMENT.Loading.service({
      fullscreen: true,
      background: "rgba(0, 0, 0, 0.7)",
      text: "Loading"
    });
    this._loadingStack.push(loadingInstance);
  },
  hide() {
    const loadingInstance = this._loadingStack.shift();
    if (this._loadingStack.length) return;
    loadingInstance && loadingInstance.close();
  }
};

点我在线预览

试验结果符合预期。