我正在设计一个功能,通过websocket提供类似自动填充的搜索结果。当用户输入的速度足够快时,他们之前的查询通常会过时,因为他们已经在询问新信息。
有没有办法识别新查询何时传入,并终止以前的查询?我尝试检查查询是否在新消息传入时进行处理,但似乎新消息仅在上一个查询(我想要取消的查询)完成后处理。当有多个用户同时搜索时,我也很困惑。
from autobahn.twisted.websocket import WebSocketServerProtocol, WebSocketServerFactory
import json
from twisted.internet.defer import Deferred, inlineCallbacks, returnValue
running = 'no'
def main_search(query): # May take up to 400ms to process
...
class SearchServerProtocol(WebSocketServerProtocol):
@inlineCallbacks
def onMessage(self, payload, isBinary):
if not isBinary:
x = json.loads(payload.decode('utf8'))
global running
try:
print running
running = 'yes'
res = yield main_search(x['query'])
running = 'no'
print x['query']
except Exception as e:
print e
self.sendClose(1000)
else:
self.sendMessage(json.dumps(res).encode('utf8'))
if __name__ == '__main__':
import sys
from twisted.python import log
from twisted.internet import reactor
log.startLogging(sys.stdout)
factory = WebSocketServerFactory("ws://104.236.31.77:8080", debug=False)
factory.protocol = SearchServerProtocol
reactor.listenTCP(8080, factory)
reactor.run()
print running
始终返回否。
谢谢!
答案 0 :(得分:1)
我认为您需要某种代表您的用户会话(或搜索会话)的上下文对象。在这种情况下,您可以放置latestSearchId
,每次搜索都会递增。然后,您可以将searchId参数添加到main_search
。假设您有一个循环或某个不同的阶段可以中止,您可以通过将它与搜索会话的latestSearchId进行比较来测试当前搜索中的searchId是否仍然是最新的。
另一种方法(例如,如果你不能中止你的搜索)可能是在计算搜索之前等待几毫秒,并检查是否有任何新搜索同时进入。
根据您的评论编辑。
你遇到的问题是你永远不应该阻止反应堆循环。您需要做的是将main_search
切成碎片,以便将控制权返回到反应堆循环中。
您是否可以执行以下操作:
def resume_search(position):
#stuff
reactor.callLater(0, resume_search, current_position)
reactor.callLater将安排在完成其工作后立即调用您的函数。你应该看到反应堆循环是一个很大的while True
基本上做了3件事
只要您的代码继续运行,它就永远不会到达其他两个代码。因此,当您插入reactor.callLater时,它将运行reactor周期,直到延迟变量(在我们的示例中可以为0)已经过去。请注意,无法保证它会及时调用您的函数。这是因为很可能某些东西正在运行(阻塞反应堆)超过指定的时间间隔。因此,您应该将此reactor.callLater(0, fun)
视为“当您不忙时给我打电话”