Мне не известно о поле, которое уже существует для этого.
Если вы можете сохранить идентификатор сокета в локальной переменной, как в варианте 2, я бы так и сделал. Обычно я предпочитаю избегать добавления произвольных полей к объектам. Однако иногда вы хотите, чтобы все приложение могло получить доступ к дополнительному фрагменту данных, и в этих случаях с использованием локальной переменной won не работает.
Добавление пользовательского поля
Вместо использования утверждения типа для any
, вы можете добавить в свой проект файл, содержащий это:
declare module "net" {
interface Socket {
id: string;
}
}
Это расширение интерфейса net.Socket
для добавления поля id
, которое является строкой. Это немного лучше, чем утверждение типа, потому что утверждение типа позволит выполнить опечатки (например, (conn as any).ids
). Я использовал ваш код, удалил утверждение типа и добавил вышеупомянутое в файл с именем externals.d.ts
который я положил рядом с .ts
файлом, содержащим ваш код. tsc
перестал жаловаться на поле. Обратите внимание, что вам не нужно импортировать этот файл или ссылаться на него каким-либо образом. У вас просто должен быть tsconfig.json
, который подхватит его вместе с остальной частью вашего источника. По умолчанию он будет выбран из-за расширения .d.ts
.
В прошлом я использовал утверждения типа и дополнения интерфейса для добавления произвольных полей к узлам DOM, и это работало просто отлично. Однако когда я это сделал, я использовал имена полей, которые были очень единичными , что означало, что была очень низкая вероятность конфликта с другими библиотеками, которые могли бы захотеть добавить свои собственные поля. Ваше имя поля id
. Меня бы беспокоили конфликты имен с другими библиотеками, которые решили, что они хотят отслеживать сокеты и добавить свое собственное поле id
в сокет.
Использование WeakMap
Есть еще один метод, который вы можете использовать. Вы можете установить WeakMap
, который связывает сокет с идентификатором. Вот иллюстрация. У вас может быть модуль socket-map
, который просто экспортирует карту, отображающую сокеты в строки:
import * as net from "net";
export const socketMap = new WeakMap<net.Socket, string>();
И тогда вы получите сокет с идентификатором, когда получите сокет:
import * as net from "net";
import * as uuid from "uuid";
import { socketMap } from "./socket-map";
var server = net.createServer();
server.on('connection', function(conn) {
const id = uuid.v4();
socketMap.set(conn, id); // You store the socket into the map.
conn.on('data', function(data) {
console.log('Session id:' + (conn as any).id);
});
});
Затем позже, в другом модуле, вы можете получить идентификатор с:
import * as net from "net";
import { socketMap } from "./socket-map";
export function foo(conn: net.Socket) {
const id = socketMap.get(conn);
}
Здесь я только что связал сокет со строкой id, но вы можете иметь любую структуру в значениях WeakMap
. Это может быть объект, который содержит целый набор информации помимо идентификатора.
Причина использования WeakMap
заключается в том, что, хотя ключи объекта WeakMap
содержат ссылки на объекты, эти ссылки не учитывают в том, что касается сбора мусора. Таким образом, если ваше приложение выполнено с сокетом и больше не ссылается на него где-либо, кроме WeakMap
, ссылка, присутствующая в WeakMap
, все еще позволит сборщику мусора сокет.