I';我正在尝试使用Twisted和jQuery(使用Django)制作一个长轮询聊天应用程序。如何将查询传递回JS?
这是我构建的第一个长轮询应用程序,也是Twisted的第二个项目,因此我非常感谢任何人对我的代码中的任何内容的反馈,因为我可能完全走错了方向 我一直在拼凑各种各样的例子,几乎可以用了,但我似乎找不到一种方法将数据返回Javascript。我在Twisted上运行了一个Django站点,它似乎运行得很好,所以除非有人认为Django的内容很重要,否则我不会将其包括在内,Django站点所做的唯一事情就是主持聊天。我最初是使用常规轮询设置的,但有人要求我将其更改为长轮询,我几乎做到了(我希望如此) 以下是HTML/JS(long.HTML): 在这里,I';我正在尝试使用Twisted和jQuery(使用Django)制作一个长轮询聊天应用程序。如何将查询传递回JS?,jquery,python,ajax,django,twisted,Jquery,Python,Ajax,Django,Twisted,这是我构建的第一个长轮询应用程序,也是Twisted的第二个项目,因此我非常感谢任何人对我的代码中的任何内容的反馈,因为我可能完全走错了方向 我一直在拼凑各种各样的例子,几乎可以用了,但我似乎找不到一种方法将数据返回Javascript。我在Twisted上运行了一个Django站点,它似乎运行得很好,所以除非有人认为Django的内容很重要,否则我不会将其包括在内,Django站点所做的唯一事情就是主持聊天。我最初是使用常规轮询设置的,但有人要求我将其更改为长轮询,我几乎做到了(我希望如此)
render
尝试getData
(它可能永远不会?),当它无法将请求放入self.delayed\u请求中时getData
使用enterprise.adbapi对Django的数据库进行查询,返回一个延迟实例processedDelayedRequests
通过延迟请求队列,如果查询完成,数据将传递到gotRows
,然后将其转换为我想要的格式,并发送到\uFormat\uResponse
,后者将数据发送回JS进行处理不管怎样,这就是理论——上一句是我认为我的问题所在
print“LAST UPDATE:”,LAST\u UPDATE
始终打印“LAST\u UPDATE:0”,但LAST\u UPDATE通过JS更新,因此这不是错误
print'MESSAGES:”,data
print“{'MESSAGES':[{'timestamp':u'2013-08-10 16:59:07.909350”,“message':u'chat message','author':u'test'},{'timestamp':u'2013-08-10 17:11:56.893340”,“message':u'hello','author':u'preference'}]”等,因为新消息被添加到数据库中。当发布帖子时,它会得到新的数据,而在其他方面,它似乎工作得很好
print“REQUEST DATA:”,DATA
根本不会触发。。。我认为这种方法是早期尝试使其工作的遗留方法
我从gotRows
中获得正确的输出,但不知道如何将该输出传递回客户端。我甚至对我对延期的理解都没有半点信心,所以我认为这就是我的问题所在,但我不知道我能做些什么来继续前进。非常感谢您的帮助。有时,twisted应用程序中的函数可能会有条件地返回数据,
在其他时间返回一个延迟的。在这种情况下,您无法查看
如果你有数据;你可能不会,在这种情况下,你会得到
延迟,任何数量的复查都不会改变这一点;你必须总是这样
函数转换为实延迟,使用,然后附加
回调到结果
也就是说,不是这样一种功能。
它总是返回一个延迟。处理这些数据的唯一方法是
附加回调。一般来说,您永远不会看到
在使
第一个电话
这意味着,由于您希望对每个长轮询请求运行查询,并且这些请求是无条件异步的(您必须在它们启动之前从render()
函数返回),因此render()
始终返回尚未完成
:
def render(self, request):
"""Handle a new request"""
request.setHeader('Content-Type', 'applicaton/json')
self.getData(request)
return server.NOT_DONE_YET
现在,一切都需要在getData中正确发生。事实证明
从runQuery
延迟的处理很好;但是sql本身有一个
. 要了解原因,请想象一个聪明的黑客试图访问
http://yoursite?last_update=5+and+"secret"+in+(select+password+from+users)
不过,修复很容易,不要进行字符串插值,而是使用绑定参数。
在查询中将%s
切换为?
,在函数中将%
切换为,
自称。当我们这样做时,让我们将连接池
移出此方法并移入\uuuu init\uuuu
,对于每个请求的每次重试,您不需要或不需要整个池
def getData(self, request):
last_update = request.args['last_update']
print "LAST UPDATE: ", last_update
new_messages = self.dbpool.runQuery("SELECT *"
" FROM chat_message"
" WHERE time > ?", request.last_update)
# ^ ^
return new_messages.addCallback(self.gotRows, request)
连接到由runQuery
返回的延迟的回调正在返回
格式化结果;但是没有人可以归还它;它需要做所有的事情
工作本身。幸运的是,我们已经给了它要处理的请求
,
所以这并不难。我们还需要处理的情况是
没有要返回的数据,因为另一端没有人将其添加到列表中
延迟请求的数量
def gotRows(self, rows, request):
if rows:
# we have data to send back to the client! actually finish the
# request here.
data = {"messages": [{'author': row[1], 'message': row[2], 'timestamp': row[3]} for
row in rows]}
request.write(self.__format_response(request, 1, data))
request.finish()
else:
self.delayed_requests.append(self)
最后,我们需要对processedDelayedRequests()
进行类似的更改
在render()
中制作。它只能触发查询,不能更新其状态
基于结果,因为它没有它们。为了简化事情,我们将
只吃清单上的东西
def processDelayedRequests(self):
delayed_requests = self.delayed_requests
self.delayed_requests = []
while self.delayed_requests:
# grab a request out of the "queue"
request = self.delayed_requests.pop()
# we can cause another attempt at getting data, but we'll never get
# to see what hapened with it in this function.
self.getData(request)
有几个实例可以检查某个方法返回值的type()
是否不是实例。您认为您为什么需要它?使用if语句筛选的数据
项是来自数据库的数据列表,应该传递给\u format\u response
;或者延迟的实例,应该重新/添加到延迟的\u请求中。ChatServer.getData()
返回的值不可能返回任何不是t.i.defer.Deferred
的内容。您可能会感兴趣此报告:
def gotRows(self, rows, request):
if rows:
# we have data to send back to the client! actually finish the
# request here.
data = {"messages": [{'author': row[1], 'message': row[2], 'timestamp': row[3]} for
row in rows]}
request.write(self.__format_response(request, 1, data))
request.finish()
else:
self.delayed_requests.append(self)
def processDelayedRequests(self):
delayed_requests = self.delayed_requests
self.delayed_requests = []
while self.delayed_requests:
# grab a request out of the "queue"
request = self.delayed_requests.pop()
# we can cause another attempt at getting data, but we'll never get
# to see what hapened with it in this function.
self.getData(request)