如何在Pylons中“刷新”响应(类似ASP Response.Write)
我有一个Pylons控制器,它是通过jQuery的$.ajaxSubmit()来调用的。这个控制器执行一个需要很长时间才能完成的操作,我希望它能在整个输出结果出来之前,先返回一些进度消息。作为一个简单的概念验证,我尝试了以下代码:
response.body_file.write('<script>OnExecutionProgress("Starting");</script>\n')
time.sleep(2)
response.body_file.write('<script>OnExecutionProgress("Finished");</script>\n')
但是,这段代码并没有立即把第一条消息返回给客户端,而是等到所有内容都处理完了才一起返回。
我之前在ASP.NET中做过类似的事情,使用了Response.Write()
和Response.Flush()
,效果很好。不过在Pylons中调用response.body_file.flush()
似乎没有什么效果。
3 个回答
0
你可以一次“产出”一部分结果。试着写一个生成器,每次只产出一小块结果,这样可能会有效果。这个方法使用了分块传输编码。
0
这确实有点像个小技巧,但在pylons中,它的工作方式和ASP.NET是一样的。我在Paste服务器上测试过。
正如Alex Martelli所说,在这种情况下,使用Comet会更好。分块发送脚本可能会导致以下问题:
- 不被支持,并且依赖于服务器的实现;
- 不可靠,因为你无法处理连接超时;
- 服务器需要为每个连接分配单独的线程,这在高负载的网站上可能会成为性能瓶颈。
首先,你应该在development.ini中关闭调试功能:
debug = false
这里是一个控制器的代码:
class HelloController(BaseController):
def index(self):
header = '''\
<html><head><title>test page</title>
<script type="text/javascript">
function foo(i) {
document.getElementById('counter').innerHTML = i;
}
</script>
</head>
<body>
<div id="counter">
</div>
'''
footer = '''\
</body>
</html>
'''
progress = ('<script>foo(%i);</script>' % i for i in xrange(0,101,2))
def f():
yield header
for script in progress:
time.sleep(1)
yield script
yield footer
return f()