我目前正在尝试了解谷歌应用引擎(gae)的任务队列。
我遇到的问题与this
非常相似因此我根据“chachan”的解决方案编写了一个小应用程序。
所以我的主要问题是如何从html网站轮询进度值。
我写了一个小的“Hello gae任务队列”应用程序,它从用户那里获取一个数字 并打印此数字,使用1到10之间的所有数字进行多次计算。计算由任务队列完成。 来源如下:
#hellogaequeue.py
import os
import time
import webapp2
import jinja2
import logging
import json
from google.appengine.api import taskqueue
template_dir = os.path.join(os.path.dirname(__file__), 'templates')
JINJA_ENV = jinja2.Environment(loader = jinja2.FileSystemLoader(template_dir), autoescape = True)
myresults = [] # the results of the task in a list
myProgressValue = 0 # represents the progess of the task. range[ 0, 100 ]
#define the main handler to show the html-site and post some data to the task.
class MainHandler(webapp2.RequestHandler):
def get(self):
#gets the calculated results of the task (therefor empty at first call)
#and give it to the jinja2 framework to render the html page
template_values = {'myresults': myresults}
counter_template = JINJA_ENV.get_template('counter.html')
self.response.out.write(counter_template.render(template_values))
# if user clicks the button, we write the data from the input field onto 'key' and
# than add a new task, with the parameter holding the value of 'key'
def post(self):
key = self.request.get('key')
# Add the task to the default queue.
taskqueue.add(url='/worker', params={'key': key})
self.redirect('/') #calls MainHandler.get(...), which shows than 'counter.html' again
#define the handler for the task worker
class TaskWorker(webapp2.RequestHandler):
def post(self):
# ensure to use the global variables
global myresults
global myProgressValue
# get the 'params={'key': key}' value
key = self.request.get('key')
#now imagine this for loop takes 5 minutes to finish
#how to show the progress of this loop in 'counter.html'
for x in xrange(1, 11):
time.sleep(1)
res = x*int(key)
myresults.append(str(res))
myProgressValue = myProgressValue + 10
class ProgressWorker(webapp2.RequestHandler):
def get(self):
global myProgressValue
logging.info("Call to ProgressHandler. MyProgressValue is = {p}".format(p=myProgressValue))
json_result = json.dumps({ "progress" : myProgressValue } )
self.response.headers['Content-Type'] = 'application/json; charset=UTF-8'
self.response.out.write(json_result)
application = webapp2.WSGIApplication( [ ('/', MainHandler), ('/worker', TaskWorker), ('/progress', ProgressWorker) ], debug=True)
'counter.html'的来源是:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello gae task queue with jQuery UI Progressbar</title>
<link rel="stylesheet" href="//code.jquery.com/ui/1.11.1/themes/smoothness/jquery-ui.css">
<script src="//code.jquery.com/jquery-1.10.2.js"></script>
<script src="//code.jquery.com/ui/1.11.1/jquery-ui.js"></script>
</head>
<body>
<form action="/" method="POST">
<input type="text" name="key" id="key">
<input type="submit" value="start gae task">
</form>
{% for counter in myresults %}
<li>
{{counter}}
</li>
{% endfor %}
<div id="progressbar"></div>
<div id="dbg"></div>
<script>
function refresh()
{
var progressVal = 0
$.ajax(
{
type: 'GET',
url: '/progress',
success: function(data)
{
var obj = JSON.parse(data);
progressVal = obj.progress;
document.getElementById("dbg").innerHTML = obj.progress;
},
error: function(xhr, status, error)
{
alert(xhr.status);
alert(error);
}
});
$( "#progressbar" ).progressbar(
{
value: progressVal
});
}
$(function()
{
setInterval("refresh()", 3000);
});
</script>
</body>
</html>
所以,第一个问题是:
为什么jquerys progressbar不起作用?
(没有警报。)
我做错了什么?
第二个问题是:
这是正确的方法吗?
考虑到for循环花费的时间超过60秒。因此无法将其放在MainHandler.post(..)函数中,因为这将导致截止日期超出错误。
我还应该提到for循环不能运行Concurrent。
额外信息: 我的gae项目的文件夹结构是:
hellogaequeue
-templates
-counter.html
-app.yaml
-hellogaequeue.py
-queue.yaml
,app.yaml看起来像:
application: queuetest-app-id
version: 1
runtime: python27
api_version: 1
threadsafe: true
libraries:
- name: jinja2
version: latest
handlers:
- url: /.*
script: hellogaequeue.application
答案 0 :(得分:1)
我终于开始工作了。
1。)问题是引用的Jquery库似乎无法正常进行进度条。 (有关更好的解释,请参阅this)
所以这里是&#34;你好任务队列的最终来源,而jquery进度条&#34;应用程式:
import os
import time
import webapp2
import jinja2
import json
from google.appengine.api import taskqueue
template_dir = os.path.join(os.path.dirname(__file__), 'templates')
JINJA_ENV = jinja2.Environment(loader = jinja2.FileSystemLoader(template_dir), autoescape = True)
myresults = []
myProgressValue = 0 #range[ 0, 100 ]
class MainHandler(webapp2.RequestHandler):
def get(self):
template_values = {'myresults': myresults, 'progressScriptActive':False}
counter_template = JINJA_ENV.get_template('counter.html')
self.response.out.write(counter_template.render(template_values))
def post(self):
key = self.request.get('key')
# Add the task to the default queue.
taskqueue.add(url='/worker', params={'key': key})
template_values = {'myresults': myresults, 'progressScriptActive':True}
counter_template = JINJA_ENV.get_template('counter.html')
self.response.out.write(counter_template.render(template_values))
class TaskWorker(webapp2.RequestHandler):
def post(self):
global myresults
global myProgressValue
key = self.request.get('key')
for x in xrange(1, 11):
time.sleep(1)
res = x*int(key)
myresults.append(str(res))
myProgressValue = myProgressValue + 10
class ProgressWorker(webapp2.RequestHandler):
def get(self):
global myProgressValue
json_result = json.dumps( myProgressValue )
self.response.headers['Content-Type'] = 'application/json; charset=UTF-8'
self.response.out.write(json_result)
application = webapp2.WSGIApplication(
[
('/', MainHandler),
('/worker', TaskWorker),
('/progress', ProgressWorker)
], debug=True)
和HTML jinja2模板(&#34; counter.html&#34;):
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello gae task queue with jQuery UI Progressbar</title>
<script src="/static/external/jquery/jquery.js"></script>
<script src="/static/jquery-ui.js"></script>
<link href="/static/jquery-ui.css" rel="stylesheet">
</head>
<body>
<form action="/" method="POST">
<input type="text" name="key" id="key">
<input type="submit" value="start gae task">
</form>
{% for counter in myresults %}
<li>
{{counter}}
</li>
{% endfor %}
<div id="progressbar"></div>
<div id="dbg"></div>
<script>
var intervalHandler = 0;
function refresh()
{
$.ajax(
{
type: 'GET',
url: '/progress',
success: function(data)
{
var progressVal = $.parseJSON( data );
document.getElementById("dbg").innerHTML = progressVal;
if( progressVal > 99 )
{
$( "#progressbar" ).progressbar( { value: 100 });
alert("Finish");
clearInterval(intervalHandler); // stop the interval
intervalHandler = null;
//window.location.reload(true);// will perform a post request, but we need a GET request
var loc = window.location;
window.location = loc.protocol + '//' + loc.host + loc.pathname + loc.search;
}
else
{
$( "#progressbar" ).progressbar( { value: progressVal });
}
},
error: function(jqXHR, textStatus, errorThrown)
{
alert("Request Error !!!!");
}
});
};
{% if progressScriptActive %}
$(function()
{
intervalHandler = setInterval("refresh()", 2000);
});
{% endif %}
</script>
</body>
</html>
您必须引用从http://jqueryui.com/download/下载的具有选定UI主题的jquery文件(不会看到任何内容!)
下载了zip并在&#34; hellogaequeue.py&#34;中引用了这些解压缩的jquery源代码。文件。 您的文件夹结构应如下所示:
hellogaequeue
-templates
-counter.html
-static
- jquery-ui.css
- jquery-ui.js
- ... and all the other unziped files/folders
-app.yaml
-hellogaequeue.py
-queue.yaml
并且对于app.yaml,你必须添加:
handlers:
- url: /static
static_dir: static
我知道这不是一个干净的解决方案,因为'progressScriptActive&#39;技巧(仅在后请求后启动轮询间隔)。 因此,如果某人有更清洁的解决方案,我会很高兴看到它。