【axios】你的进度条准确吗

1、axios监听进度

上传和下载操作在前端中是非常常见的,当我们想知道上传或下载的进度时也不难,axios已经实现了监听进度的方法

import axios from 'axios'

// 上传请求
axios.post('/api/v1/upload', {
    data: xxx
  },
  {
    // onUploadProgress回调可以获取进度
    onUploadProgress(e) {
      const complete = e.loaded / e.total * 100
    }
	}
)

// 或者
axios({
  method: 'POST',
  data: {
    data: xxx
  },
  onUploadProgress(e) {
    const complete = e.loaded / e.total * 100
  }
})

翻一下axios的源码,看看它是如何实现的
在/lib/adapters/xhr.js文件中,可以看到这么一段代码

let request = new XMLHttpRequest()

// Not all browsers support upload events
if (typeof config.onUploadProgress === 'function' && request.upload) {
  request.upload.addEventListener('progress', progressEventReducer(config.onUploadProgress));
}

axios是基于XMLHttpRequest来实现的

其中,config就是我们传给的axios的参数,如果是上传操作并且有传递onUploadProgress函数的话
就监听XMLHttpRequest的progress事件,然后周期性地触发回调函数progressEventReducer
再看一下progressEventReducer的实现:

function progressEventReducer(listener, isDownloadStream) {
  return e => {
    const loaded = e.loaded;
    const total = e.lengthComputable ? e.total : undefined;
    ...

    const data = {
      loaded,
      total,
      progress: total ? (loaded / total) : undefined,
      ...
    };

    data[isDownloadStream ? 'download' : 'upload'] = true;  // 区别上传或是下载

    listener(data);
  };
}

在progressEventReducer中,就会获取

  • loaded:已上传的buffer数据流
  • total:总的buffer数据流

最终会将数据传给listener,即一开始传给axios的onUploadProgress回调,所以我们可以通过e.loaded / e.total来获取进度

2、不准确的进度条

获取进度条很简单,但是在实际使用中还是碰到了问题

- 计算出来的进度与实际上传进度不符合

在这里插入图片描述

- 可以看出:进度条已经走完,但是接口一直在pending中

这个问题还是比较严重的,明明显示完成了上传,但是文件就是没有出来
而且文件越大,差异就越明显

原因

造成这个原因,其实跟TCP协议发送数据的方式有关

  • 在客户端,会有一个send buffer,即数据缓存区
  • 这个buffer缓存区存储的就是等待发送的数据,tcp协议层会在适当的时候选取一部分数据发送出去
  • 当我们上传文件时,数据会被不断地write到这个缓存区;每次写入时就会被侦听到,然后调用一次onUploadProgress,e.loaded其实表示的就是写入到buffer缓存区的数据
  • 但是此时的数据可能还没有被发送出去,仍然在缓存区中放着;加上发送数据也需要时间
  • 等到数据全部到达Server的时候,才会执行response回调,这时候上传操作才算完成;但客户端那边早就显示发送完毕了,时差也就出来了
    在这里插入图片描述

3、模拟进度条

如果解决这个问题呢?有一个比较保守的做法:用一个亦真亦假的进度条

在进度达到一定值的时候,开始人为干涉;每次让它走一点,给人一种一直在上传的感觉,直到上传完成,赋值为100即可

这里就使用vue3的方式实现一下:

import { ref } from 'vue'

/**
 * 模拟进度条
 * @returns
 */
export const useProgress = (name: string) => {
  const progress = ref<number>(0)
  const timer = ref<number | null>(null)

  const onUploadProgress = (e: ProgressEvent) => {
    const complete = (e.loaded / e.total) * 100

    // 超过80 开始干涉
    if (complete >= 80) {
      if (timer.value) return
      timer.value = window.setInterval(() => {
        progress.value += (100 - progress.value) * 0.2  // 每次增加剩下的20%
        
        // 超过99 不再变化(此时也接近上传完成了)
        if (progress.value > 99) {
          timer.value && window.clearInterval(timer.value)
        }, 1000)
      } else {
      // 在80之前都按照axios计算出的进度来显示
      progress.value = complete
    }
	}
  
  return {
    progress,
    onUploadProgress
  }
}

可以在请求完成的时候,将progress设置为100即可
具体的阈值可以根据情况自行设置

其实,大名鼎鼎的NProgress库也是这么做的,我们平时使用它的姿势是这样的:

NProgress.start()  // 开启进度条

NProgress.done()  // 进度条结束

可是,又没有监听接口,仅仅只是开启进度条,它怎么能预测我们的进度呢?
答案是:它也是模拟进度条
在其源码中,有这么一段代码:

当我们没有传amount的时候,会自动根据当前进度条的status调整每次的进度amount
当进度staus超过0.994的时候,就会一直停在0.994这个状态
直到我们执行NProgress.done()时,会直接调用NProgress.set(1),进度条走完

参考:
https://github.com/axios/axios
https://github.com/rstacruz/nprogress

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/448670.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SSM整合项目(删除家居 + 分页查询)

1.删除家居 1.需求分析 2.编写Service层 1.FurnService.java 添加方法 //删除家居public void del(Integer id);2.FurnServiceImpl.java 实现方法 Overridepublic void del(Integer id) {furnMapper.deleteByPrimaryKey(id);}3.单元测试 Testpublic void del() {furnService.…

JavaScript基础6之执行上下文、作用域链、函数创建、函数激活、checkScope的执行过程、闭包、this

JavaScript基础 执行上下文执行上下文中的属性变量对象全局上下文的变量对象函数上下文执行过程进入执行上下文代码执行思考题 作用域链函数创建函数激活checkScope的执行过程总结 闭包分析闭包 this 执行上下文 执行上下文中的属性 每一个执行上下文都有三个核心属性 变量对…

haproxy-高性能负载均衡反向代理服务

目录 一、HAProxy&#xff08;High Availability Proxy&#xff09;概述 1、HAProxy的概念 2、HAProxy的主要特性 3、HAProxy的优缺点 4、Haproxy负载均衡策略 5、LVS、nginx、HAProxy的区别 二、安装HAProxy 1、yum安装 2、第三方rpm包安装 3、编译安装 3.1 解决 l…

【AI视频教程】只需5步,AI作出鸡你太美视频

1.视频效果 2.准备工作 制作视频效果&#xff0c;需要准备下面3个条件&#xff1a; 准备stable diffusion的环境剪辑一段【鸡你太美】原版视频stable diffusion安装sd-webui-IS-NET-pro插件 2.1部署stable diffusion环境 这里还是建议大家用云平台部署stable diffusion&am…

一个测开人员的大厂面试总结

前言 其实我已经入职有好一段时间了&#xff0c; 这里决定总结一下一些面试经验。 我呢&#xff0c;最终还是决定要离开服务了 5 年多的公司。 而这次跳槽历经 3 个月&#xff0c;前后聊了 10 家公司&#xff0c;进行了将近 40 场面试, 基本都是 41 的流程 (技术面 HR 面)&…

计算机网络-第5章 运输层(2)

5.6 TCP可靠传输实现 以字节为单位的滑动窗口。 发送窗口已满&#xff0c;停止发送。 发送和接收的数据都来自缓存。 超时重传时间RTO选择&#xff1a;自适应算法&#xff0c; 选择确认SACK&#xff1a;只传送缺少的数据。大多数实现还是重传所有未被确认的数据块。 5.7 TCP的…

小程序学习 1

pages/goods/search/home.wxml首页功能设定 1. loading入场 2. 下拉刷新 3. 搜索栏 4. 分类切换 5. 商品列表 6. 规格弹层 7. 加载更多 <view style"text-align: center; color: #b9b9b9" wx:if"{{pageLoading}}"><t-loading theme"circula…

网络安全防御保护 Day7

1.因为FW1和FW2已处于双机热备状态&#xff0c;所以只需要对主设备进行配置即可。进入FW1的配置界面&#xff0c;选择“网络”界面&#xff0c;点击“IPsec”&#xff0c;进行IPsec通道的基本配置&#xff0c;这里选择的是“电信”链路。 2.完成上述配置后&#xff0c;进行待加…

面试官:线程调用2次start会怎样?我支支吾吾没答上来

写在开头 在写完上一篇文章《Java面试必考题之线程的生命周期&#xff0c;结合源码&#xff0c;透彻讲解!》后&#xff0c;本以为这个小知识点就总结完了。 但刚刚吃晚饭时&#xff0c;突然想到了多年前自己面试时的亲身经历&#xff0c;决定再回来补充一个小知识点&#xff…

【DPDK】基于dpdk实现用户态UDP网络协议栈

文章目录 一.背景及导言二.协议栈架构设计1. 数据包接收和发送引擎2. 协议解析3. 数据包处理逻辑 三.网络函数编写1.socket2.bind3.recvfrom4.sendto5.close 四.总结 一.背景及导言 在当今数字化的世界中&#xff0c;网络通信的高性能和低延迟对于许多应用至关重要。而用户态网…

并发通信(网络进程线程)

如果为每个客户端创建一个进程&#xff08;或线程&#xff09;&#xff0c;因为linux系统文件标识符最多1024位&#xff0c;是有限的。 所以使用IO复用技术&#xff0c;提高并发程度。 阻塞与非阻塞 阻塞式复用 非阻塞复用 信号驱动IO 在属主进程&#xff08;线程中声明&…

4、Generator、class类、继承、Set、Map、Promise

一、生成器函数Generator 1、声明generator函数 function* 函数名() { }调用生成器函数 需要next()返回一个generator对象&#xff0c;对象的原型上有一个next(),调用返回对象{value:yield后面的值,done} function* fn() {console.log("我是生成器函数") } let it…

JAVA开发常见小问题整合

文章目录 1&#xff1a;身份证工具类相关方法1.1 身份证脱敏处理 2&#xff1a;字符串补零处理(此处是JAVA类的方法&#xff0c;并无引用StrUtil)3&#xff1a;springboot前后端分离&#xff0c;后端返回json字符串带斜杠问题处理4&#xff1a;WebUploader 文件上传组件 -编辑回…

java基本认识?java跨平台原理?jdk、jre、jvm的联系?

1、java基本认识 1.1 java语言 语言&#xff1a;人与人交流沟通的方式。比如&#xff0c;你好、hello等。 计算机语言&#xff1a;人与计算机之间进行信息交流的一种特殊方式。比如&#xff0c;Java语言、C语言、C等。 1.2 java的来源 Java 是由 Sun Microsystems 公司于 …

如何正确选择国外服务器的带宽和线路呢?

国外大带宽服务器是一种提供高带宽、高速网络连接和良好稳定性的服务器&#xff0c;但在中国使用这类服务器可能涉及到违反法律法规的风险。因此我无法为你提供相关帮助。接下来和源库一起了解如何正确选择国外服务器的带宽和线路呢? 考虑目标用户的地理位置。如果目标用户主要…

计算机网络-第5章 运输层(1)

主要内容&#xff1a;进程之间的通信与端口、UDP协议、TCP协议、可靠传输原理&#xff08;停止等待协议、ARQ协议&#xff09;、TCP报文首部、TCP三大题&#xff1a;滑动窗口、流量控制、拥塞控制机制 5.1 运输层协议概述 运输层向它上面的应用层提供通信服务&#xff0c;真正…

window Zookeeper 启动;

文章目录 前言一、Zookeeper 介绍&#xff1a;二、window 使用&#xff1a;2.1 下载&#xff1a;2.2 启动2.3 连接&#xff1a; 总结 前言 本文对window Zookeeper zk 启动 进行介绍&#xff1b; 一、Zookeeper 介绍&#xff1a; ZooKeeper 是一个开源的分布式协调服务&#…

辽宁博学优晨教育:视频剪辑培训的安全正规之路

在当今数字化时代&#xff0c;视频剪辑已成为一项炙手可热的技能。为满足广大学习者的需求&#xff0c;辽宁博学优晨教育推出了一系列专业的视频剪辑培训课程。本文将重点介绍辽宁博学优晨教育的视频剪辑培训如何在保障学员安全和学习效果方面做出了卓越的努力。 一、正规资质&…

PID控制器组(完整SCL代码)

PID控制器组不是什么新概念,是在PID控制器的基础上,利用面向对象的思想对对象进行封装 批量实例化。 1、增量式PID https://rxxw-control.blog.csdn.net/article/details/124363197https://rxxw-control.blog.csdn.net/article/details/1243631972、完全增量式PID https:/…

5款好用的AI办公软件,一键轻松制作PPT、视频,提升工作效率!

众所周知&#xff0c;AI 人工智能技术已渗透到生活的方方面面&#xff0c;无论是很多人早已用上的智能音箱、语音助手&#xff0c;还是新近诞生的各种 AI 软件工具&#xff0c;背后都离不开 AI 人工智能技术的加持。 对于各类新生的 AI 软件工具&#xff0c;人们很容易「选边站…