有些页面加载过程中会显示进度条,或者是一个百分的比例,从 0 到 100 一点点显示。或者是加载一个文件图片,到 100%了显示出来。
就比如说我现在用 ajax 请求一个后台的文件,后台应该是不可能知道前端请求的进度的吧,那么前端是用的啥技术才可以显示加载的百分比呢,想问一下这是哪块的技术,求指导
1
knightdf 2018-02-22 16:48:56 +08:00
卡在 99%不就行了:dog:
|
2
edison111cry OP @knightdf 以前做过一个上传文件的,需要展示上传的百分比数字,当时确实时卡在 99%时再用 ajax 去查询这个文件是否已经存在服务器上了,如果没有隔 3 秒再查,如果已经有了,就结束。
难道大神们都是这么做的? |
3
loading 2018-02-22 16:56:12 +08:00 via iPhone
进度条,只要在动就行了。是算不准的。
不信你搜索 win10 的重启更新进度条,233 |
4
hxsf 2018-02-22 16:59:57 +08:00 10
原理:
http header: Content-Length 表明了响应的总长度。 当前接受到的 / Content-Length = 进度 实现: xhr 的 progress Event fetch 的 Response.body 上的 getReader() , render 可以读原始字节流,然后计算当前进度。 |
5
edison111cry OP @hxsf 多谢,原来是这样。
|
6
whypool 2018-02-22 17:08:45 +08:00 1
document.readyState 可以判断状态,用这个模拟加载百分比
一般会迅速飙到 90%,剩下的 10%递归加一点,直到浏览器抛出 complete,退出递归进度百分比设置为 100%,取消 loading 动画 除非后端返回百分比,否则拿不到真实的加载百分比 |
7
whypool 2018-02-22 17:14:58 +08:00
@hxsf 这玩意并不能计算出总体百分比,只能拿到当前文档的大小,然而并发的或者异步的 json,css,js,图片这些资源,得服务器先响应 header 才能叠加计算,单个文件还 ok,多个就蛋疼
|
8
learnshare 2018-02-22 17:15:50 +08:00
单个文件如 @hxsf 所讲的方法
网页加载无法实时反映加载进度,因为可能直到最后一个文件加载完毕,才会知道数据总量 |
9
RihcardLu 2018-02-22 17:17:25 +08:00
技术的角度都说了,说点用户心里有关的。其实进度条的准确度可能不是那么重要,只要给用户那么个东西,『我正在加载,马上就完成了』,用户就会等待更久的时间(相比于什么提示都没有的页面)。
|
10
chairuosen 2018-02-22 17:25:41 +08:00
单说网页加载:
<script src='lib1.js'></script> <script>setProgressBar(30)</script> <script src='lib2.js'></script> <script>setProgressBar(60)</script> <script src='lib3.js'></script> <script>setProgressBar(100)</script> |
11
edison111cry OP @chairuosen 我擦,这样倒真是个方法。 不错不错,学习了
|
12
hxsf 2018-02-22 17:51:03 +08:00
@learnshare #8
1. 链接建立拿到 header -> 更新 total size 2. 拿到内容 -> 更新 current size 如: 1s:189 / 800 3s: 772 / 1723 5s: 2300 / 2300 done! 或者 当前文件进度:123 / 6123B 总进度: 26 / 89 个 因为对于浏览器来说,加载资源可能是多个同时进行的。所以后者不好做。 前者就够了。 |
13
learnshare 2018-02-22 18:01:52 +08:00
@hxsf 已下载量和总量都在变化,进度是要倒退的
再说,分析关联文件这种事太复杂,除了浏览器本身,其他的都没必要去做 |
14
hxsf 2018-02-22 18:13:10 +08:00 1
@learnshare #13 进度变小,你可以倒退,也可以等待啊。
有没有必要做,看需求和收益,不是单看复杂不复杂,真有需求,写个 loader 又何妨呢。 LZ 只是问怎么做。我给了答案。 做不做,看 LZ 自己喽。 |
15
vuuv 2018-02-22 21:45:40 +08:00 via Android
具体进度主要靠人工提供。
最简单的就是达到某一阶段提升一个进度。 例如 0-10-40-70-100 进度条突然暴增体验不佳,然后有了一些改进来优化体验。 例如设定 0-10 一般需要 2s,那么进度条缓慢增加,如果你花 1 秒完成了,就突然从 5 跳到 10,如果迟迟没有收到通知,则会卡在 10。 可惜还是略感不佳,你可以增加额外的判断来动态调整时长。 例如一开始根据加载速度计算初始时长在 1-3 秒波动。如果 0.5 秒完成了,则加快后续的进度增幅。如果 5 秒才完成,则降低后续的进度增幅。 如此依次将前一阶段的进度耗时计入下一周期,这样可能看起来时快时慢,但是可以获得相对平滑的进度提示了。 后面是我的改进思路,实际上我只做到了第二步。 |
16
vuuv 2018-02-22 21:51:55 +08:00 via Android
我上面主要是针对多种耗时不等的情况的。
任务复杂也可以拆分到多个进度条里提示。然后提示所处阶段。 至于单一任务,上面提到实时计算就挺好的。额外设置定时动画反而不好。 进度条主要是告诉用户等待时间,以便客户决定是否“离开一会儿”,避免干等浪费时间。 |
17
vuuv 2018-02-22 22:12:05 +08:00 via Android
特别提醒,我最后构思的持续进度条可能存在部分负优化。
按照我的思路,如果设定 0-10 耗时 2s 完成动画,如果迟迟没有回应,则会在 2s 后占用下一进度的区间(向 40 进发),不过增幅逐步缓慢下来。在 0-10 完成后,根据之前的延时降低 10-40 的进度增幅。 如果出现意外导致相应阶段无法完成,这会造成一种它还活着的假象,造成误导。白等浪费时间不说,还会提供错误的进度信息。 |
18
nciyuan 2018-02-22 23:05:17 +08:00 via Android
原来 Flash 可以,但是现在不行了。
最基本就是数据大小 /总大小 一般用户上传这种知道大小的可以直接给条,像是提交表单,或者动态数据,可以处理完一部分加一点 要是不定的或者别的直接动画 用条的也尽可能不要卡在 99%,因为如果等待时间很长那么到了 99%用户是不想刷新的 还有小的数据网速快的话条还没加载好数据都传完了 |
19
Humorce 2018-02-22 23:34:38 +08:00 via iPhone
最牛逼的还是分明一秒处理完,硬要加个 3 秒的进度动画的
|
21
geelaw 2018-02-22 23:47:50 +08:00 via iPhone
@loading 如果你说的是安装补丁,那用的是 **不确定** 进度环,本来就没有进度多少的指示;如果你说的是升级安装系统,那么那个进度环是在反应安装进度的,因此可以出现不动一段时间的情况。
|
22
hxsf 2018-02-23 08:21:55 +08:00 via iPhone
@azh7138m chunk 传输才没有 content length,一般来说流式传输动态内容时才会使用 chunk,普通静态内容都是非 chunk 的
|
23
azh7138m 2018-02-23 08:46:53 +08:00 via Android
@hxsf
> When a message does not have a Transfer-Encoding header field, a Content-Length header field can provide the anticipated size 在现代,并不应该假定 content length 是存在的,gzip 很常见 |
24
hxsf 2018-02-23 09:47:35 +08:00
@azh7138m #23 是很常见啊,不过都是针对文本内容的。对于 图片、字体、媒体资源,依然可以知道总大小。
PS: gzip 一般是在 content-encoding Transfer-Encoding 一般才是 chunk gzip 是可以得知 length 的。不过就需要 server 用 buffer 缓存压缩后的内容,全部压缩完后得到大小在发送(比较伤,所以一般 server 采用 gzip、br 等后就分块传输(可以流式编码了))。 而对于 js、css 等文本资源,一般文件较小的没有加载进度的需求吧,只有数量较多、总体较大的文件要加载时,才有这个需求,如果服务器不返回 size,则可以采用 已加载数量 /总数量 的方式。 |