1 回答

TA貢獻(xiàn)1848條經(jīng)驗(yàn) 獲得超10個(gè)贊
也許不是完整的解決方案,但只是一些想法..
第一個(gè)好的改變是,他們的客戶(服務(wù)員)是一個(gè) set() ,它確保默認(rèn)情況下每個(gè)客戶只包含一次。它作為類變量進(jìn)行定義和訪問(wèn)。因此,您不使用 self.waiters 而是使用 cls.waiters 或 ClassName.waiters (在本例中為 ChatSocketHandler.waiters)來(lái)訪問(wèn)它。
class?ChatSocketHandler(tornado.websocket.WebSocketHandler): ????waiters?=?set()
第二個(gè)變化是它們以 @classmethod 的形式更新每個(gè)客戶端(您可以在此處選擇將更新發(fā)送給部分客戶端而不是全部客戶端),因?yàn)樗鼈儾幌虢邮諏?shí)例(self)而是類(cls)并引用類變量(在本例中為 waiter、cache 和 cach_size)
我們可以在這里忘記緩存和緩存大小。
像這樣:
@classmethod
? ? def send_updates(cls, chat):
? ? ? ? logging.info("sending message to %d waiters", len(cls.waiters))
? ? ? ? for waiter in cls.waiters:
? ? ? ? ? ? try:
? ? ? ? ? ? ? ? waiter.write_message(chat)
? ? ? ? ? ? except:
? ? ? ? ? ? ? ? logging.error("Error sending message", exc_info=True)
每次 API 調(diào)用時(shí),都會(huì)創(chuàng)建處理程序的新實(shí)例,稱為self
.?并且中的每個(gè)參數(shù)self
對(duì)于實(shí)例來(lái)說(shuō)都是唯一的,并且與調(diào)用您的方法的實(shí)際客戶端相關(guān)。這有助于在每次通話時(shí)識(shí)別客戶。因此,基于實(shí)例的客戶端列表(如 (self.clients))在每次調(diào)用時(shí)始終為空。添加客戶端只會(huì)將其添加到該實(shí)例的世界視圖中。
但有時(shí)您希望一些變量(例如客戶端列表)對(duì)于從您的類創(chuàng)建的所有實(shí)例都相同。這就是類變量(直接在類定義下定義的變量)和@classmethod
裝飾器發(fā)揮作用的地方。
@classmethod
使方法調(diào)用獨(dú)立于實(shí)例。這意味著您只能訪問(wèn)這些方法中的類變量。但對(duì)于消息代理來(lái)說(shuō),這正是我們想要的:
將客戶端添加到類變量中,該變量對(duì)于處理程序的所有實(shí)例都是相同的。由于它被定義為一個(gè)集合,因此每個(gè)客戶端都是唯一的。
接收消息時(shí),將其發(fā)送給所有(或一部分客戶端)
so
on_message
是一個(gè)“正?!睂?shí)例方法,但它調(diào)用類似:最后send_updates()
是 a 。@classmethod
send_updates() 迭代所有(或子集)客戶端(服務(wù)員)并最終使用它來(lái)發(fā)送實(shí)際更新。
從例子來(lái)看:
@classmethod
? ? def send_updates(cls, chat):
? ? ? ? logging.info("sending message to %d waiters", len(cls.waiters))
? ? ? ? for waiter in cls.waiters:
? ? ? ? ? ? try:
? ? ? ? ? ? ? ? waiter.write_message(chat)
? ? ? ? ? ? except:
? ? ? ? ? ? ? ? logging.error("Error sending message", exc_info=True)
請(qǐng)記住,您使用 waiters.append(self) 添加了服務(wù)員,因此每個(gè)服務(wù)員實(shí)際上都是一個(gè)實(shí)例,并且您“簡(jiǎn)單地”調(diào)用實(shí)例(該實(shí)例代表調(diào)用者) write_message() 方法。所以這不是廣播,而是一一發(fā)送給每一個(gè)來(lái)電者。您可以在此處按某些標(biāo)準(zhǔn)(例如主題或組)進(jìn)行分隔...
簡(jiǎn)而言之:用于@classmethod獨(dú)立于特定實(shí)例(例如您的情況下的調(diào)用者或客戶端)的方法,并且您希望對(duì)“所有”或“所有”客戶端的子集執(zhí)行操作。但您只能在這些方法中訪問(wèn)類變量。這應(yīng)該沒(méi)問(wèn)題,因?yàn)檫@是他們的目的;)
添加回答
舉報(bào)