Skip to content

HqManager (股票行情管理器)

管理股票实时行情数据的获取与订阅,自动根据 App 版本选择协议:

  • 期货通 iOS < 037.08.389:使用 getHQ 原生接口
  • 其他平台/版本:使用 UnifiedRequestBridge

类型声明

typescript
type CodeWithMarket = string;  // 格式: "股票代码_市场代码",如 "300033_33"

type StockHqInfo = {
  code: string;             // 股票代码(字段 4)
  market: string;           // 市场代码(字段 34338)
  price: string;            // 最新价(字段 10)
  priceChangeRatio: string; // 涨跌幅(字段 34818)
  name?: string;            // 股票名称(字段 55)
  high?: string;            // 最高价(字段 233)
  low?: string;             // 最低价(字段 9)
  time?: string;            // 时间(字段 1)
  pre: string;              // 昨收价(字段 6)
  priceChange: string;       // 涨跌额(字段 34821)
  [key: string]: string | undefined;
};

type AllStockHqInfo = Record<CodeWithMarket, StockHqInfo>;

type HqRequestParams = {
  protocolId: string;
  pageId: string;
  onlineId: string;
  requestDic: string;
  actionType?: 'unSubscribe';   // 取消订阅时追加
  _stocks?: CodeWithMarket[];   // getHQ 协议内部使用
  _columOrder?: string[];        // getHQ 协议内部使用
};

class HqManager {
  debug: boolean;
  invoked: boolean;
  connecting: boolean;
  connectDelay: number;
  visible: boolean;
  error: any;
  onlineId: string;
  protocolId: number;
  pageId: number;
  columOrder: string[];
  logTableFields: string[];
  callback: (res: AllStockHqInfo) => void;
  readonly codeWithMarkets: CodeWithMarket[];

  constructor(config: {
    onlineId: string;
    debug?: boolean;
    connectDelay?: number;
    protocolId?: number;
    pageId?: number;
    columOrder?: string[];
    callback: (res: AllStockHqInfo) => void;
  });

  registerStocks(stocks: Array<CodeWithMarket>): void;
  unregisterStocks(stocks: Array<CodeWithMarket>): void;
  clearStocks(): void;
  connect(): Promise<void>;
  disconnect(): void;
  destroy(): void;
  handleHqData(rawData: Record<string, string[]>): void;
  log(...args: any[]): void;
}

构造参数

参数类型必填默认值说明
onlineIdstring订阅唯一标识,用于区分多个 HqManager 实例、取消订阅和返回数据分发
callbackfunction行情数据推送回调,接收 AllStockHqInfo
debugbooleanfalse开启调试日志
connectDelaynumber100重连延迟(毫秒),首次连接不延迟
protocolIdnumber1264协议 ID(getHQ 模式下不生效)
pageIdnumber9001页面 ID(getHQ 模式下不生效)
columOrderstring[]['4', '34338', '10', '34818', '55']请求字段顺序

实例属性

属性类型默认值说明
codeWithMarketsCodeWithMarket[][]只读,当前已注册的股票列表(去重后)
erroranynull最近一次请求或解析错误,无错误时为 null
visiblebooleantrue当前页面可见状态,由 onShow/onHide 自动管理
invokedbooleanfalse是否已完成首次连接(首次连接不延迟)
connectingbooleanfalse是否正在延迟重连中

方法

registerStocks(stocks)

注册股票并建立连接。使用引用计数机制:同一股票多次注册会增加计数,只有在股票为新加入时才触发重连。

  • stocks: Array<CodeWithMarket> — 股票代码数组,格式为 "代码_市场"

unregisterStocks(stocks)

取消注册股票。使用引用计数:只有当计数减至 0 时才从列表移除,移除后触发重连。

  • stocks: Array<CodeWithMarket> — 要取消的股票代码数组

clearStocks()

清空所有已注册股票,发送空订阅请求断开数据推送。

connect()

手动触发连接/重连。首次连接立即执行,后续每次重连会等待 connectDelay 毫秒防抖。内部使用版本号机制防止并发重连导致的脏请求。

disconnect()

断开当前连接,清理 native 端的订阅回调。

destroy()

销毁实例:

  1. 清空所有股票引用
  2. 断开连接
  3. 移除 native 端的 handler 注册
  4. 清除 window.hqIns / window.hqIns_${onlineId} 引用(debug 模式下)
  5. 标记实例为已销毁,后续生命周期回调不再执行

handleHqData(rawData)

处理原始行情数据,将列式数据转换为按股票组织的 AllStockHqInfo 对象后回调 callback

  • rawData: Record<string, string[]> — 原始数据,key 为字段编号(或映射后的字段名),value 为按股票索引排列的值数组

log(...args)

调试日志输出,仅在 debug: true 时输出到控制台,格式为 [HqManager:${onlineId}:${时间}]

示例

typescript
import { HqManager } from '@fu/matrix';

// 创建实例
const hqManager = new HqManager({
  onlineId: 'my-app',
  debug: true,
  callback: res => {
    console.log('行情数据:', res);
    // {
    //   "300033_33": { "code": "300033", "market": "33", "price": "100.01", "priceChangeRatio": "0%",
    //                  "name": "同花顺", "pre": "99.50", "priceChange": "0.51" },
    //   "000099_33": { "code": "000099", "market": "33", "price": "15.16", "priceChangeRatio": "-1.24%",
    //                  "name": "中信信息", "pre": "15.35", "priceChange": "-0.19" }
    // }
  }
});

// 注册股票(新股票会触发重连,已有股票不会重复)
hqManager.registerStocks(['300033_33', '000099_33']);
hqManager.registerStocks(['600519_11']); // 新增一只,触发重连

// 取消部分股票(同一股票需要 unregister 同等次数才能移除)
hqManager.unregisterStocks(['000099_33']);

// 查看当前订阅的股票
console.log(hqManager.codeWithMarkets); // ["300033_33", "600519_11"]

// 清空全部订阅
hqManager.clearStocks();

// 断开连接(保留注册列表)
hqManager.disconnect();

// 销毁实例(完全清理)
hqManager.destroy();

工作原理

  1. 注册股票registerStocks 使用引用计数(_stockRefs Map),同一股票多次注册会累加计数,只有新加入的股票才会触发重连;unregisterStocks 递减计数,计数归零时才真正移除并重连;clearStocks 清空全部并发送空请求断开推送
  2. 建立连接 — 首次 connect 立即执行,后续每次重连会等待 connectDelay 防抖。内部使用 connectVersion 版本号机制,延迟结束后若版本号已变更则放弃本次请求
  3. 数据推送 — 统一注册 UnifiedRequestBridge(或 getHQ)回调,根据返回头部的 onlineId 分发到对应实例
  4. 数据转换handleHqData 将原始列式数据(每个字段对应一个数组)通过 mapFields 映射字段名后,按股票索引重组为 AllStockHqInfo 对象
  5. 生命周期管理 — 自动监听页面显示/隐藏(onShow/onHide),切后台时断开连接并递增版本号,回前台时自动重连。destroy 后不再响应生命周期事件

环境行为

环境桥接模式订阅取消订阅
AndroidAndroid 模式WebViewJavascriptBridge.callOnlineHandler('UnifiedRequestBridge', onlineId, params)WebViewJavascriptBridge.clearOnlineHandler([onlineId])
iOS(>= 037.08.389)iOS 模式callNativeHandler('UnifiedRequestBridge', params)在原请求参数上追加 actionType: 'unSubscribe'
期货通 iOS(< 037.08.389)getHQ 模式callNativeHandler('getHQ', {stocklist, marketlist, columnorder})callNativeHandler('getHQ', {method:'disconnect'})
期货通鸿蒙Android 模式同 Android同 Android
手炒/iFind 鸿蒙iOS 模式同 iOS同 iOS

协议选择由 bridge 层通过 isHigherInnerVersion 自动检测,调用方无需关心。

协议差异

UnifiedRequestBridgegetHQ
适用平台iOS / Android / 鸿蒙仅期货通 iOS(< 037.08.389)
多实例隔离支持,按 onlineId 路由部分支持,所有实例的 stocks 合并发送
protocolId / pageId支持自定义不支持,原生接口无此参数
请求格式{protocolId, pageId, onlineId, requestDic}{stocklist, marketlist, columnorder}
取消订阅actionType: 'unSubscribe'{method: 'disconnect'} 清空全部
适用场景复杂订阅,多页面并行简单取数,单页面使用

注意:getHQ 模式存在兼容性限制,无法指定 protocolIdpageId,构造函数中相关配置项在该模式下不生效。该模式仅用于旧版期货通 iOS 的行情兼容,不建议在新业务中依赖。getHQ 模式下多个实例的股票列表会合并后统一发送给 native。

调试

开启 debug: true 后:

  • 实例暴露到 window.hqInswindow.hqIns_${onlineId}
  • 连接参数和行情数据输出到控制台
  • 使用 console.tablelogTableFields 字段格式化输出行情数据

注意事项

  • 股票代码格式为 代码_市场,如 300033_33(300033 是股票代码,33 是市场代码)
  • onlineId 必填,多实例时请使用不同的 onlineId 来隔离,重复 ID 会打印警告
  • destroy() 会同时清理 window.hqIns / window.hqIns_${onlineId} 引用并移除 native handler
  • registerStocks 使用引用计数,同一股票注册 N 次需要 unregisterStocks N 次才能移除;新股票加入才会触发重连
  • clearStocks() 会发送空订阅请求断开推送,而 disconnect() 只断开连接不清空列表
  • getHQ 模式下 protocolId / pageId 配置不生效,无法指定特定协议
  • visible 属性由生命周期自动管理,页面隐藏时断开连接,显示时自动重连