多个请求下 loading 的展示与关闭

简介: 多个请求下 loading 的展示与关闭

一般情况下,在 vue 中结合 axios 的拦截器控制 loading 展示和关闭,是这样的:

App.vue 配置一个全局 loading。

<div class="app">
        <keep-alive :include="keepAliveData">
            <router-view/>
        </keep-alive>
        <div class="loading" v-show="isShowLoading">
            <Spin size="large"></Spin>
        </div>
    </div>

同时设置 axios 拦截器。

// 添加请求拦截器
this.$axios.interceptors.request.use(config => {
     this.isShowLoading = true
     return config
 }, error => {
     this.isShowLoading = false
     return Promise.reject(error)
 })
// 添加响应拦截器
this.$axios.interceptors.response.use(response => {
     this.isShowLoading = false
     return response
 }, error => {
     this.isShowLoading = false
     return Promise.reject(error)
 })

这个拦截器的功能是在请求前打开 loading,请求结束或出错时关闭 loading。

如果每次只有一个请求,这样运行是没问题的。但同时有多个请求并发,就会有问题了。

举例

假如现在同时发起两个请求,在请求前,拦截器 this.isShowLoading = true 将 loading 打开。

现在有一个请求结束了。this.isShowLoading = false 拦截器关闭 loading,但是另一个请求由于某些原因并没有结束。

造成的后果就是页面请求还没完成,loading 却关闭了,用户会以为页面加载完成了,结果页面不能正常运行,导致用户体验不好。

解决方案

增加一个 loadingCount 变量,用来计算请求的次数。

loadingCount: 0

再增加两个方法,来对 loadingCount 进行增减操作。

methods: {
        addLoading() {
            this.isShowLoading = true
            this.loadingCount++
        },
        isCloseLoading() {
            this.loadingCount--
            if (this.loadingCount == 0) {
                this.isShowLoading = false
            }
        }
    }

现在拦截器变成这样:

// 添加请求拦截器
        this.$axios.interceptors.request.use(config => {
            this.addLoading()
            return config
        }, error => {
            this.isShowLoading = false
            this.loadingCount = 0
            this.$Message.error('网络异常,请稍后再试')
            return Promise.reject(error)
        })
        // 添加响应拦截器
        this.$axios.interceptors.response.use(response => {
            this.isCloseLoading()
            return response
        }, error => {
            this.isShowLoading = false
            this.loadingCount = 0
            this.$Message.error('网络异常,请稍后再试')
            return Promise.reject(error)
        })

这个拦截器的功能是:

每当发起一个请求,打开 loading,同时 loadingCount 加1。

每当一个请求结束, loadingCount 减1,并判断 loadingCount 是否为 0,如果为 0,则关闭 loading。

这样即可解决,多个请求下有某个请求提前结束,导致 loading 关闭的问题。

切换路由时,取消之前的请求

使用 axios,可以在切换路由时把之前没完成的请求取消掉。

具体分析请看这篇文章axios切换路由取消指定请求与取消重复请求并存方案。下面展示一下实现效果:

我新建了一个 Vue 项目,设置了 ab 两个路由,每次进入路由时,发起一个 get 请求:

// a.vue
<template>
    <div class="about">
        <h1>This is an a page</h1>
    </div>
</template>
<script>
import { fetchAData } from '@/api'
export default {
    created() {
        fetchAData().then(res => {
            console.log('a 路由请求完成')
        })
    }
}
</script>
// b.vue
<template>
    <div class="about">
        <h1>This is an b page</h1>
    </div>
</template>
<script>
import { fetchBData } from '@/api'
export default {
    created() {
        fetchBData().then(res => {
            console.log('b 路由请求完成')
        })
    }
}
</script>

从上图可以看到,每当进入路由时会发起一个请求,请求完成后打印一句话。现在我把网速调低,然后每次点击 a 路由时,马上就切换到 b 路由。目的是为了取消 a 路由页面的请求(页面中的黑条就是 loading 图)。

下面的动图是实验效果:

可以看到,成功取消了 a 路由页面的请求。

我把这个 Vue DEMO 项目放上 github 了,有兴趣可以亲自试一下。

目录
相关文章
|
10月前
|
前端开发
`Promise.all()`方法在处理数组形式参数时的执行机制
Promise.all()` 提供了一种方便的方式来同时处理多个异步操作,并在它们都完成后获取到所有的结果,使得我们能够更高效地进行异步任务的组合和处理。
|
JavaScript UED
以 Vue 3 项目为例,多个请求下如何全局封装 Loading 的展示与关闭?其中大有学问!
以 Vue 3 项目为例,多个请求下如何全局封装 Loading 的展示与关闭?其中大有学问!
|
JavaScript
基于Vue2超简单实现DIY定制的步骤条
这篇文章介绍了如何在Vue 2中实现一个自定义设计的步骤条组件,包括子组件的设计和在父页面中的使用示例。
335 1
基于Vue2超简单实现DIY定制的步骤条
|
安全 应用服务中间件 网络安全
简单比较 http https http2,我们要如何把http升级为https
【9月更文挑战第13天】本文对比了HTTP、HTTPS和HTTP/2的特点与适用场景。HTTP以明文传输,适合低安全要求的环境;HTTPS通过SSL/TLS加密,适用于电子商务等安全要求高的场景;HTTP/2采用二进制格式和多路复用,适合高性能Web应用。文章还详细介绍了将HTTP升级为HTTPS的步骤,包括申请和安装SSL证书、配置Web服务器、重定向HTTP流量到HTTPS以及测试HTTPS功能。升级到HTTPS可提高数据安全性和用户信任度。
366 13
|
12月前
|
小程序 JavaScript 开发者
微信小程序分包的相关概念和使用
本文介绍了微信小程序分包的概念、优势、配置方法、加载规则、体积限制,以及独立分包和分包预下载的配置,旨在帮助开发者优化小程序的加载速度和开发效率。
|
11月前
|
监控 关系型数据库 MySQL
如何升级MySQL数据库?
【10月更文挑战第16天】如何升级MySQL数据库?
Flutter 学习之图片的选择、裁切、保存
Flutter 学习之图片的选择、裁切、保存 在Flutter中,我们可以通过调用系统的图片选择器来选择一张图片,也可以通过使用插件来实现图片的裁切和保存。
623 0
|
运维 负载均衡 Java
nacos常见问题之单机nacos2.2.3线程池异常如何解决
Nacos是阿里云开源的服务发现和配置管理平台,用于构建动态微服务应用架构;本汇总针对Nacos在实际应用中用户常遇到的问题进行了归纳和解答,旨在帮助开发者和运维人员高效解决使用Nacos时的各类疑难杂症。
|
前端开发 JavaScript
前端开发领域中,require和import这两个重要的关键字到底有啥区别?
前端开发领域中,require和import这两个重要的关键字到底有啥区别?
261 3
|
JavaScript 前端开发 程序员
前端程序员入门:先学Vue3还是Vue2?
前端程序员入门:先学Vue3还是Vue2?
1426 0