V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
pppy
V2EX  ›  Python

如何实现实时的进度条?

  •  
  •   pppy · 2016-10-28 19:26:34 +08:00 · 7290 次点击
    这是一个创建于 2737 天前的主题,其中的信息可能已经有所发展或是发生改变。
    提交数据后,可能需要时间执行,后端如何与前端保持一个同步的进度显示?
    比如后台执行到 20% 前端就显示 20%
    21 条回复    2016-10-29 22:43:42 +08:00
    lcorange
        1
    lcorange  
       2016-10-28 19:36:40 +08:00
    1. 前台 js 定时访问拿数据
    2. websocket
    alqaz
        2
    alqaz  
       2016-10-28 20:07:44 +08:00 via Android
    难点估计不在交互,在于怎么判断任务执行百分比
    mayne95
        3
    mayne95  
       2016-10-28 20:55:05 +08:00
    后端执行一点功能就往前面返回一个状态。感觉这么搞负担好大。而且我看网站都是一点就过去了,速度都很快,单纯的为了视觉效果弄个假的糊弄算了。 gmail 加载好像跟你这个需求差不多。
    ihuotui
        4
    ihuotui  
       2016-10-28 20:59:13 +08:00 via Android
    大概就行了,根据数据量预估一个时间,然后剩下一点等待服务器返回成功
    Powered
        5
    Powered  
       2016-10-28 21:08:48 +08:00
    三种思路:

    1. WebSocket
    2. 内嵌一个 iframe,写一个 timer 不停去刷新 iframe 中的内容(iframe 的 src 属性指向你的长耗时任务的 URL),根据内容字符串的最后一个百分号的值,获得进度。
    3. 使用 ajax XMLHttpRequest level 2 API

    给出一个例子:

    后端:

    ```javascript
    'use strict';

    const http = require('http');

    const server = http.createServer();
    server.on('request', function(req, res) {
    console.log('HTTP', req.method, req.url);
    let n = 0;
    res.writeHead(200, {
    'Content-Type': 'text/plain',
    'Connection': 'keep-alive',
    'Access-Control-Allow-Origin': '*',
    'Content-Length': 100
    });

    const inter = setInterval(function() {
    res.write('.');
    n++;
    if (n >= 100) {
    clearInterval(inter);
    res.end();
    }
    }, 50);

    res.on('error', function(err) {
    console.log(err);
    });

    res.on('close', function() {
    console.log('Connection close');
    })
    });

    server.listen(8000);

    ```


    前端:

    ```html
    <!DOCTYPE html>
    <HTML>
    <head>
    <meta charset="utf-8"/>
    <style>
    .progress-bar {
    border: 1px solid rgb(230, 230, 230);
    padding: 0px;
    position: relative;
    height: 4px;
    border-radius: 2px;
    }

    .progress-bar > .progress-bar-inner {
    margin: 0px;
    width: 30%;
    background-color: rgb(0, 180, 20);
    height: 4px;
    border-radius: 2px;
    }
    </style>
    </head>
    <body>
    <div class="progress-bar">
    <div id="pro" class="progress-bar-inner"></div>
    </div>
    <script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
    <script>
    var progress = $('#pro');
    var xhr = new XMLHttpRequest();
    xhr.open('GET', 'http://localhost:8000/', true);
    xhr.onprogress = function(event) {
    if (event.lengthComputable) {
    var pro = event.loaded/event.total;
    console.log(pro);
    progress.css('width', pro*100 + '%');
    }
    };
    xhr.send();
    </script>
    </body>
    </HTML>
    ```
    Powered
        6
    Powered  
       2016-10-28 21:09:13 +08:00
    上面的例子使用使用 ajax XMLHttpRequest level 2 API 做的
    eyp82
        7
    eyp82  
       2016-10-28 21:10:34 +08:00
    没有必要, 你观察一下就会发现大多数的进度条都是假的, 只是视觉安慰而已.
    除非你真的需要根据这个进度条精确定位(但其实这个很难, 比如很难估计一项任务到底要花多少时间)
    shlabc
        8
    shlabc  
       2016-10-28 21:20:59 +08:00
    前端用 Flash 编程,可以做到实时
    adv007
        9
    adv007  
       2016-10-28 22:10:59 +08:00 via iPhone
    @shlabc 啥年代了,还 fla
    adv007
        10
    adv007  
       2016-10-28 22:11:34 +08:00 via iPhone
    websocket http-chunk
    shlabc
        11
    shlabc  
       2016-10-28 22:17:41 +08:00
    @adv007 呵呵,我只是说这个技术绝对能做到啊
    silencefent
        12
    silencefent  
       2016-10-28 23:08:25 +08:00
    卡 99%好吧,解决了就 100%
    SourceMan
        13
    SourceMan  
       2016-10-28 23:10:24 +08:00 via iPhone
    你看看苹果的"少于一分钟",你就知道你现在这个需求有没有意义了
    guyskk
        14
    guyskk  
       2016-10-29 00:58:54 +08:00 via Android
    我记得有个讨论是说: 数据是从客户端发送出去的,客户端本身就应该知道已经发送了多少数据,也就能知道百分比,为何要询问服务端自己已经知道的事情?

    现在 XMLHttpRequest 有上传进度的接口,具体可以在 MDN 找到。 5 楼的实现是正确的,也可以去翻 jQuery 等涉及 AJAX 的库源码,应该能找到上传进度的实现,我之前也是在一个库里看到的,不过一时找不到在哪了。
    akmonde
        15
    akmonde  
       2016-10-29 09:36:29 +08:00
    很多进度条都是假的,一般按大段的工作进度来分。
    qwer1234asdf
        16
    qwer1234asdf  
       2016-10-29 14:38:46 +08:00 via iPhone
    ajaxForm
    coolloves
        18
    coolloves  
       2016-10-29 17:22:48 +08:00 via Android
    马克,关注下
    Mark24
        19
    Mark24  
       2016-10-29 18:23:20 +08:00
    前天洗澡的时候也想过这个问题。
    可以建立一个 cache=[ ], 在里面塞任务队列,然后计算长度,完成一个往前推进一步。恩,至少这个是可行的。
    Tyanboot
        20
    Tyanboot  
       2016-10-29 19:53:22 +08:00 via Android
    @guyskk 他说的应该是那种,前端发送数据之后,后端需要长时间执行然后返回结果的那种吧。
    guyskk
        21
    guyskk  
       2016-10-29 22:43:42 +08:00 via Android
    @Tyanboot 重新看了一下题目,确实是我看错了,多谢提醒
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2236 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 00:36 · PVG 08:36 · LAX 17:36 · JFK 20:36
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.