#javascript #node.js #typescript #singleton
#javascript #node.js #typescript #синглтон
Вопрос:
Я пытаюсь создать синглтон, который имеет одно соединение amqp, и когда вызывается метод CreateChannel, он должен возвращать новый канал из того же соединения:
export interface IBroker {
createChannel(): Promise<IChannel>;
}
export default class Broker implements IBroker {
private static instance: Broker;
private conn: IConnection | undefined;
private constructor(public config: IRabbitMQConfig = new RabbitMQConfig()) {}
/**
* singleton
*/
public static getInstance(): Broker {
if (!this.instance) {
this.instance = new Broker();
}
return this.instance;
}
/**
* initiates configuration on infra service
*/
async createChannel(): Promise<IChannel> {
try {
if (!this.conn) {
this.conn = await this.config.init();
await this.createExchanges();
await this.createQueues();
await this.createBinds();
logger.info('Broker started successfully');
}
if (!this.conn) {
throw new InternalError('Error starting broker. Missing connection!');
}
return await this.conn.createChannel();
} catch (err) {
logger.error('Error trying to start broker', err);
throw new InternalError('Error trying to start broker', 500);
}
}
// code...
вызов config.init() возвращает соединение amqp.
когда я тестирую класс, как показано ниже, каждый раз, когда я вызываю CreateChannel, он создает новое соединение!
const a = Broker.getInstance();
const b = Broker.getInstance();
console.log(a === b); // return true
a.createChannel(); // create a new connection
b.createChannel(); // creates another connection
this.conn класса Broker всегда не определен при вызове CreateChannel!
Комментарии:
1. Как вы определяете, что он устанавливает новое соединение? Всегда ли первая
if (!this.conn)
ветвь вычисляетсяtrue
как?2. Я зарегистрировал this.conn, каждый раз, когда я вызываю метод CreateChannel брокера, он не определен! и успешно запущенный брокер сообщений тоже всегда отображается.
3. Разве вы не должны ожидать
createChannel
вызовов? К моменту вашего вызоваb.createChannel
, скорееasync
всего, операция по его инициализации еще не завершена.4. конечно, это проблема.. Извините, что беспокою вас этой глупой ошибкой … большое вам спасибо!
Ответ №1:
Я думаю, проблема в том, что два синхронных вызова createChannel
означают, что первый не инициализировал соединение к моменту вызова второго, что приводит к созданию 2 соединений.
Если вы хотите сделать свой createChannel
«потокобезопасный» с точки зрения создания соединения, вы могли бы сделать что-то вроде этого (непроверенный):
interface IConnection {
connect: () => void
}
const initConnection = () : Promise<IConnection> => {
return Promise.resolve({
connect: () => {}
});
};
class Broker {
private connection : IConnection | undefined;
private pendingConnection : Promise<IConnection> | undefined;
async createChannel() : Promise<IConnection> {
if (this.connection) {
return this.connection;
}
if (this.pendingConnection) {
return this.pendingConnection;
}
this.pendingConnection = initConnection();
const conn = await this.pendingConnection;
// Do other setup stuff
this.connection = conn;
this.pendingConnection = undefined;
return conn;
}
}