I';我正在尝试使用Twisted和jQuery(使用Django)制作一个长轮询聊天应用程序。如何将查询传递回JS?

I';我正在尝试使用Twisted和jQuery(使用Django)制作一个长轮询聊天应用程序。如何将查询传递回JS?,jquery,python,ajax,django,twisted,Jquery,Python,Ajax,Django,Twisted,这是我构建的第一个长轮询应用程序,也是Twisted的第二个项目,因此我非常感谢任何人对我的代码中的任何内容的反馈,因为我可能完全走错了方向 我一直在拼凑各种各样的例子,几乎可以用了,但我似乎找不到一种方法将数据返回Javascript。我在Twisted上运行了一个Django站点,它似乎运行得很好,所以除非有人认为Django的内容很重要,否则我不会将其包括在内,Django站点所做的唯一事情就是主持聊天。我最初是使用常规轮询设置的,但有人要求我将其更改为长轮询,我几乎做到了(我希望如此)

这是我构建的第一个长轮询应用程序,也是Twisted的第二个项目,因此我非常感谢任何人对我的代码中的任何内容的反馈,因为我可能完全走错了方向

我一直在拼凑各种各样的例子,几乎可以用了,但我似乎找不到一种方法将数据返回Javascript。我在Twisted上运行了一个Django站点,它似乎运行得很好,所以除非有人认为Django的内容很重要,否则我不会将其包括在内,Django站点所做的唯一事情就是主持聊天。我最初是使用常规轮询设置的,但有人要求我将其更改为长轮询,我几乎做到了(我希望如此)

以下是HTML/JS(long.HTML):

在这里,
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)