feat(market-ranking): 完善行情订阅生命周期
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
export const EVENT_TCP_RECONNECT = 'tcpReconnect';
|
||||
|
||||
export type EventListener = () => void;
|
||||
|
||||
// 模拟客户端事件总线,后续可在真实 TCP 重连回调中调用 emit。
|
||||
export class EventEmitter {
|
||||
private static readonly instance: EventEmitter = new EventEmitter();
|
||||
private listeners: Map<string, EventListener[]> = new Map<string, EventListener[]>();
|
||||
|
||||
private constructor() {
|
||||
}
|
||||
|
||||
static getInstance(): EventEmitter {
|
||||
return EventEmitter.instance;
|
||||
}
|
||||
|
||||
on(eventName: string, listener: EventListener): void {
|
||||
const eventListeners = this.listeners.get(eventName);
|
||||
if (eventListeners === undefined) {
|
||||
this.listeners.set(eventName, [listener]);
|
||||
return;
|
||||
}
|
||||
if (!eventListeners.includes(listener)) {
|
||||
eventListeners.push(listener);
|
||||
}
|
||||
}
|
||||
|
||||
off(eventName: string, listener: EventListener): void {
|
||||
const eventListeners = this.listeners.get(eventName);
|
||||
if (eventListeners === undefined) {
|
||||
return;
|
||||
}
|
||||
const listenerIndex = eventListeners.indexOf(listener);
|
||||
if (listenerIndex >= 0) {
|
||||
eventListeners.splice(listenerIndex, 1);
|
||||
}
|
||||
if (eventListeners.length === 0) {
|
||||
this.listeners.delete(eventName);
|
||||
}
|
||||
}
|
||||
|
||||
emit(eventName: string): void {
|
||||
const eventListeners = this.listeners.get(eventName);
|
||||
if (eventListeners === undefined) {
|
||||
return;
|
||||
}
|
||||
eventListeners.slice().forEach((listener: EventListener): void => {
|
||||
listener();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export const emitter: EventEmitter = EventEmitter.getInstance();
|
||||
@@ -8,6 +8,11 @@ import { MarketRankingDataFetcher } from './MarketRankingDataFetcher';
|
||||
import { MarketRankingHqRequestClient } from './MarketRankingHqRequestClient';
|
||||
import { formatGreatNumber, formatPercent, riseFallColor } from '../common/NumberFormat';
|
||||
import { AllCardsCard } from '../common/AllCardsModels';
|
||||
import {
|
||||
emitter,
|
||||
EVENT_TCP_RECONNECT,
|
||||
EventListener,
|
||||
} from '../common/EventEmitter';
|
||||
import {
|
||||
INFO_IMAGE_DARK,
|
||||
INFO_IMAGE_LIGHT,
|
||||
@@ -32,11 +37,20 @@ export struct MarketRankingNodeComponent {
|
||||
@State tabContentWidth: number = 0;
|
||||
@State tabScrollOffset: number = 0;
|
||||
@State showExplainSheet: boolean = false;
|
||||
@StorageLink('enableDarkMode') isDarkMode: boolean = false;
|
||||
@Link @Watch('onRefreshTriggerChange') refreshTrigger: number; //todo
|
||||
@Consume('firstPageVisible') @Watch('onFirstPageVisibleChange') firstPageVisible: boolean = true;
|
||||
@StorageLink('enableDarkMode') isDarkMode: boolean = false; //todo
|
||||
private hqUnsubscribe: (() => void) | undefined;
|
||||
private tcpReconnectListener: EventListener = (): void => {
|
||||
this.onTcpReconnect();
|
||||
};
|
||||
|
||||
aboutToAppear(): void {
|
||||
this.updateCardConfig();
|
||||
emitter.on(EVENT_TCP_RECONNECT, this.tcpReconnectListener);
|
||||
if (!this.firstPageVisible) {
|
||||
return;
|
||||
}
|
||||
// Mock 网络延迟:模拟真实接口返回前的等待过程,接入真实请求后移除该 setTimeout。
|
||||
setTimeout(() => {
|
||||
this.updateCardData(this.primaryIdx, this.secondaryIdx);
|
||||
@@ -44,6 +58,7 @@ export struct MarketRankingNodeComponent {
|
||||
}
|
||||
|
||||
aboutToDisappear(): void {
|
||||
emitter.off(EVENT_TCP_RECONNECT, this.tcpReconnectListener);
|
||||
this.stopSubscribeHq();
|
||||
}
|
||||
|
||||
@@ -52,6 +67,37 @@ export struct MarketRankingNodeComponent {
|
||||
this.cardConfig = MarketRankingDataFetcher.getInstance().fetchCardConfig();
|
||||
}
|
||||
|
||||
// refreshTrigger 变化时重新获取当前 Tab 的合约,并在请求完成后重建行情订阅。
|
||||
onRefreshTriggerChange(): void {
|
||||
this.updateCardData(this.primaryIdx, this.secondaryIdx);
|
||||
}
|
||||
|
||||
// 页面不可见时停止行情;恢复可见后使用已有合约重建订阅。
|
||||
onFirstPageVisibleChange(): void {
|
||||
if (!this.firstPageVisible) {
|
||||
this.stopSubscribeHq();
|
||||
return;
|
||||
}
|
||||
if (this.cardData.tableList.length > 0) {
|
||||
this.subscribeHq(this.primaryIdx, this.secondaryIdx);
|
||||
return;
|
||||
}
|
||||
this.updateCardData(this.primaryIdx, this.secondaryIdx);
|
||||
}
|
||||
|
||||
// 收到 TCP 重连事件后,仅在页面可见时重新订阅行情。
|
||||
private onTcpReconnect(): void {
|
||||
if (!this.firstPageVisible) {
|
||||
return;
|
||||
}
|
||||
this.stopSubscribeHq();
|
||||
if (this.cardData.tableList.length > 0) {
|
||||
this.subscribeHq(this.primaryIdx, this.secondaryIdx);
|
||||
return;
|
||||
}
|
||||
this.updateCardData(this.primaryIdx, this.secondaryIdx);
|
||||
}
|
||||
|
||||
@Builder
|
||||
CardTitle() {
|
||||
Row({ space: 4 }) {
|
||||
@@ -361,7 +407,9 @@ export struct MarketRankingNodeComponent {
|
||||
name: contract.contract_name,
|
||||
})),
|
||||
};
|
||||
this.subscribeHq(primaryIdx, secondaryIdx);
|
||||
if (this.firstPageVisible) {
|
||||
this.subscribeHq(primaryIdx, secondaryIdx);
|
||||
}
|
||||
} catch {
|
||||
this.cardData = { tableList: [] };
|
||||
}
|
||||
|
||||
@@ -6,6 +6,9 @@ import { AiPickNodeComponent } from '../ai-pick/AiPickNodeComponent';
|
||||
@Entry
|
||||
@Component
|
||||
struct Index {
|
||||
@State refreshTrigger: number = 0;
|
||||
@Provide('firstPageVisible') firstPageVisible: boolean = true;
|
||||
|
||||
build() {
|
||||
Scroll() {
|
||||
Column({ space: 8 }) {
|
||||
@@ -13,7 +16,9 @@ struct Index {
|
||||
AIView()
|
||||
}
|
||||
Card() {
|
||||
MarketRankingNodeComponent()
|
||||
MarketRankingNodeComponent({
|
||||
refreshTrigger: $refreshTrigger,
|
||||
})
|
||||
}
|
||||
Card() {
|
||||
AiPickNodeComponent()
|
||||
|
||||
Reference in New Issue
Block a user