基于脚本进度的动态进度条?

5
我有一个使用webapp2框架与MySQL数据库交互的Google App Engine应用程序。应用程序的用户可以上传数据。在上传过程中,我想显示进度条,因为这可能需要几分钟时间。
根据我在其他主题中看到的(主要是:这个主题这个主题),我正在研究JSON/Javascript解决方案,这对我来说都是新的。
如果我传递一个随机数,进度条本身就可以工作。但是,我无法弄清楚如何从Python脚本中“加载”变化的值。
以下是HTML/CSS/Javascript代码:
HTML:
<div id="myProgress">
    <div id="myBar"</div>
</div>  

CSS:
#myProgress {width: 300px;
height: 30px;
background-color: #ddd;
}
#myBar {width: 1%;
height: 30px;
background-color: #4CAF50;
}   

Javascript:     
<script type="text/javascript">
function move() {
    var elem = document.getElementById("myBar");   
    var width = 1;
    var id = setInterval(frame, 1000);
    function frame() {
        if (width >= 100) {
            clearInterval(id);
        } 
        else {
            //var randomnumber = Math.floor(Math.random() * 100); --> works
            var randomnumber = function update_values() {
                $SCRIPT_ROOT = {{ script_root }};
                $.getJSON($SCRIPT_ROOT+"/uploading",
                    function(data) {
                        $("#width").text(data.width+" %")
                    });
            } ; --> this is wrong I assume
            var width = randomnumber; 
            elem.style.width = width + '%'; 
        }
    }
}
window.onload=move();   
</script>

进度条的进度是由嵌入在加载页面脚本中的Python for循环控制的。当脚本完成一个活动后,我希望计数器的结果能够传递给进度条作为其宽度。对于静态变量,我使用常规的Jinja方式。

class UploadingpageHandler(webapp2.RequestHandler):
def get(self):
    activities_list = [1,2,3,4,5,6,7,8,9,10]
    counter = 0
    script_root = 'localhost:10080'

    for activity in activities_list:
        counter = counter + 10
        upload.do_stuff_in_some_function_with_MySQL()   
        obj = {
        'width': counter
        }
        self.response.headers['Content-Type'] = 'application/json' --> this
        self.response.out.write(json.dumps(obj)) --> and this is wrong I assume

    template_vars = {
    'script_root': script_root
    }
    template = jinja_environment.get_template('uploading.html')
    self.response.out.write(template.render(template_vars))

如何修改脚本使其工作?或者有更好的解决方法吗?

一个简单的带进度条的ajax上传... https://stackoverflow.com/questions/26674575/php-upload-extract-and-progressbar/26679480#26679480 这个例子是用PHP提交的,但稍加修改后,我相信对你也会起作用。 - NewToJS
谢谢您的回复。我仍然不确定如何修改所提出的解决方案...您能否在哪些部分上给我更多指导,以便在JavaScript中获取正确的变量?我还在寻找一种从Python脚本中加载值的方法。 - Pieter
如果您正在上传某些内容,您不需要让Python传递任何东西,只需让它处理上传即可。我已经添加了事件监听器来监听上传的过程。因此,runprogress(event)将计算0-100的进程,因此,如果您添加console.log(percent),您将看到它记录0到100。uploadcomplete(event)将在上传完成后执行,因此您可以使用它来设置状态消息并清除/重置进度条。至于对ajax post的更改,您应该能够将upload.php更改为要使用的服务器端文件。 - NewToJS
这对于POSTGET方法都应该是一样的,它将在原地计算ajax调用的进度。 - NewToJS
啊,我明白了。再问一个问题以确保这将导致解决方案。用户点击“上传”后,会向另一个网站的API发出Python请求。因此,不是用户本身在上传文件,就像示例中一样,而是我想要在进度条中显示的一系列请求的进度。那还能行吗? - Pieter
如果数据通过Ajax传递,则ajax必须等待调用的回复...这是计算响应。例如,上传照片...客户端选择了一张照片,ajax将该照片发布到服务器端文件... ajax知道服务器端正在处理它,因此我在其中的事件正在侦听并在该过程更改时进行更新,因此为0-100。 - NewToJS
1个回答

1
你需要在函数外部的某个地方存储你的“活动”进度。
一个不太优雅的“解决方案”是将其存储到一些缓存解决方案中,如memcached或redis,并使用某种时间戳/签名来检索它(并使用类似cron job的方式使旧条目无效)。
或者你可以选择完全使用异步任务,例如Celery,但我怀疑你无法在Google App Engine上这样做。

1
谢谢!我想我以前尝试过Celery。如果我没记错的话,它不能与GAE一起使用。GAE确实有自己的任务队列(https://cloud.google.com/appengine/docs/standard/python/taskqueue/)。那个能做同样的事吗?如果不行,我也会研究memcached和redis... - Pieter
那个GAE任务队列似乎正是你所需要的。因为这是一系列请求,我认为最好的解决方案确实是任务队列,但开发它是一个漫长的过程。我会权衡开发成本和进度条的真正需求。这是你的网站的主要组成部分吗?如果是,处理这些任务(包括重试等能力)是关键。如果不是,那么也许重新考虑你正在尝试做什么或者完全放弃进度条。 - airstrike
一种新颖的方法是将这10个任务(或者正如你所说的活动)分解成10个单独的API入口,然后在客户端处理这些任务的“调度”,而不是像当前Python函数中的循环。基本上,一旦任务1完成(你可以通过ajax请求的回调触发这个事件),就开始任务2。这样,你就可以用复杂的JS代码(可能会失去某些功能,比如重试任务)来替换开发Python任务队列系统的成本。 - airstrike
谢谢!重新思考是否真的有必要是关键,能提出这个问题很好 :) 我认为解决方案将是估算所需时间,将该数字作为静态数字发送到模板,然后让JavaScript在设定的间隔内递增条形进度条。但在尝试@NewToJS提到的Ajax解决方案之前,请不要这样做。 - Pieter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接