页面加载时,进度条/百分比的是靠什么技术获得到底加载了百分比例的 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
edison111cry
V2EX    问与答

页面加载时,进度条/百分比的是靠什么技术获得到底加载了百分比例的

 
  •   edison111cry 2018-02-22 16:43:57 +08:00 8212 次点击
    这是一个创建于 2839 天前的主题,其中的信息可能已经有所发展或是发生改变。

    有些页面加载过程中会显示进度条,或者是一个百分的比例,从 0 到 100 一点点显示。或者是加载一个文件图片,到 100%了显示出来。

    就比如说我现在用 ajax 请求一个后台的文件,后台应该是不可能知道前端请求的进度的吧,那么前端是用的啥技术才可以显示加载的百分比呢,想问一下这是哪块的技术,求指导

    24 条回复    2018-02-23 09:47:35 +08:00
    knightdf
        1
    knightdf  
       2018-02-22 16:48:56 +08:00
    卡在 99%不就行了:dog:
    edison111cry
        2
    edison111cry  
    OP
       2018-02-22 16:55:53 +08:00   1
    @knightdf 以前做过一个上传文件的,需要展示上传的百分比数字,当时确实时卡在 99%时再用 ajax 去查询这个文件是否已经存在服务器上了,如果没有隔 3 秒再查,如果已经有了,就结束。

    难道大神们都是这么做的?
    loading
        3
    loading  
       2018-02-22 16:56:12 +08:00 via iPhone
    进度条,只要在动就行了。是算不准的。
    不信你搜索 win10 的重启更新进度条,233
    hxsf
        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 可以读原始字节流,然后计算当前进度。
    edison111cry
        5
    edison111cry  
    OP
       2018-02-22 17:02:25 +08:00
    @hxsf 多谢,原来是这样。
    whypool
        6
    whypool  
       2018-02-22 17:08:45 +08:00   1
    document.readyState 可以判断状态,用这个模拟加载百分比
    一般会迅速飙到 90%,剩下的 10%递归加一点,直到浏览器抛出 complete,退出递归进度百分比设置为 100%,取消 loading 动画
    除非后端返回百分比,否则拿不到真实的加载百分比
    whypool
        7
    whypool  
       2018-02-22 17:14:58 +08:00
    @hxsf 这玩意并不能计算出总体百分比,只能拿到当前文档的大小,然而并发的或者异步的 json,css,js,图片这些资源,得服务器先响应 header 才能叠加计算,单个文件还 ok,多个就蛋疼
    learnshare
        8
    learnshare  
       2018-02-22 17:15:50 +08:00
    单个文件如 @hxsf 所讲的方法
    网页加载无法实时反映加载进度,因为可能直到最后一个文件加载完毕,才会知道数据总量
    kechx
        9
    kechx  
       2018-02-22 17:17:25 +08:00
    技术的角度都说了,说点用户心里有关的。其实进度条的准确度可能不是那么重要,只要给用户那么个东西,『我正在加载,马上就完成了』,用户就会等待更久的时间(相比于什么提示都没有的页面)。
    chairuosen
        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>
    edison111cry
        11
    edison111cry  
    OP
       2018-02-22 17:27:00 +08:00
    @chairuosen 我擦,这样倒真是个方法。 不错不错,学习了
    hxsf
        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 个

    因为对于浏览器来说,加载资源可能是多个同时进行的。所以后者不好做。 前者就够了。
    learnshare
        13
    learnshare  
       2018-02-22 18:01:52 +08:00
    @hxsf 已下载量和总量都在变化,进度是要倒退的
    再说,分析关联文件这种事太复杂,除了浏览器本身,其他的都没必要去做
    hxsf
        14
    hxsf  
       2018-02-22 18:13:10 +08:00   1
    @learnshare #13 进度变小,你可以倒退,也可以等待啊。
    有没有必要做,看需求和收益,不是单看复杂不复杂,真有需求,写个 loader 又何妨呢。
    LZ 只是问怎么做。我给了答案。
    做不做,看 LZ 自己喽。
    vuuv
        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 秒才完成,则降低后续的进度增幅。
    如此依次将前一阶段的进度耗时计入下一周期,这样可能看起来时快时慢,但是可以获得相对平滑的进度提示了。

    后面是我的改进思路,实际上我只做到了第二步。
    vuuv
        16
    vuuv  
       2018-02-22 21:51:55 +08:00 via Android
    我上面主要是针对多种耗时不等的情况的。
    任务复杂也可以拆分到多个进度条里提示。然后提示所处阶段。

    至于单一任务,上面提到实时计算就挺好的。额外设置定时动画反而不好。

    进度条主要是告诉用户等待时间,以便客户决定是否“离开一会儿”,避免干等浪费时间。
    vuuv
        17
    vuuv  
       2018-02-22 22:12:05 +08:00 via Android
    特别提醒,我最后构思的持续进度条可能存在部分负优化。

    按照我的思路,如果设定 0-10 耗时 2s 完成动画,如果迟迟没有回应,则会在 2s 后占用下一进度的区间(向 40 进发),不过增幅逐步缓慢下来。在 0-10 完成后,根据之前的延时降低 10-40 的进度增幅。

    如果出现意外导致相应阶段无法完成,这会造成一种它还活着的假象,造成误导。白等浪费时间不说,还会提供错误的进度信息。
    nciyuan
        18
    nciyuan  
       2018-02-22 23:05:17 +08:00 via Android
    原来 Flash 可以,但是现在不行了。
    最基本就是数据大小 /总大小
    一般用户上传这种知道大小的可以直接给条,像是提交表单,或者动态数据,可以处理完一部分加一点
    要是不定的或者别的直接动画
    用条的也尽可能不要卡在 99%,因为如果等待时间很长那么到了 99%用户是不想刷新的
    还有小的数据网速快的话条还没加载好数据都传完了
    rzti483NAJ66l669
        19
    rzti483NAJ66l669  
       2018-02-22 23:34:38 +08:00 via iPhone
    最牛逼的还是分明一秒处理完,硬要加个 3 秒的进度动画的
    azh7138m
        20
    azh7138m  
       2018-02-22 23:40:56 +08:00 via Android
    @hxsf 老哥,content length 又不是一定会有,gzip 了解一下
    geelaw
        21
    geelaw  
       2018-02-22 23:47:50 +08:00 via iPhone
    @loading 如果你说的是安装补丁,那用的是 **不确定** 进度环,本来就没有进度多少的指示;如果你说的是升级安装系统,那么那个进度环是在反应安装进度的,因此可以出现不动一段时间的情况。
    hxsf
        22
    hxsf  
       2018-02-23 08:21:55 +08:00 via iPhone
    @azh7138m chunk 传输才没有 content length,一般来说流式传输动态内容时才会使用 chunk,普通静态内容都是非 chunk 的
    azh7138m
        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 很常见
    hxsf
        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,则可以采用 已加载数量 /总数量 的方式。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5632 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 01:45 PVG 09:45 LAX 17:45 JFK 20:45
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86